Source Code Cross Referenced for JList.java in  » 6.0-JDK-Core » swing » javax » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package javax.swing;
0027
0028        import java.awt.event.*;
0029        import java.awt.*;
0030
0031        import java.util.Vector;
0032        import java.util.Locale;
0033
0034        import java.beans.*;
0035
0036        import javax.swing.event.*;
0037        import javax.accessibility.*;
0038        import javax.swing.plaf.*;
0039        import javax.swing.text.Position;
0040
0041        import java.io.ObjectOutputStream;
0042        import java.io.ObjectInputStream;
0043        import java.io.IOException;
0044        import java.io.Serializable;
0045
0046        import sun.swing.SwingUtilities2;
0047        import sun.swing.SwingUtilities2.Section;
0048        import static sun.swing.SwingUtilities2.Section.*;
0049
0050        /**
0051         * A component that displays a list of objects and allows the user to select
0052         * one or more items. A separate model, {@code ListModel}, maintains the
0053         * contents of the list.
0054         * <p>
0055         * It's easy to display an array or Vector of objects, using the {@code JList}
0056         * constructor that automatically builds a read-only {@code ListModel} instance
0057         * for you:
0058         * <pre>
0059         * // Create a JList that displays strings from an array
0060         *
0061         * String[] data = {"one", "two", "three", "four"};
0062         * JList myList = new JList(data);
0063         *
0064         * // Create a JList that displays the superclasses of JList.class, by
0065         * // creating it with a Vector populated with this data
0066         *
0067         * Vector superClasses = new Vector();
0068         * Class rootClass = javax.swing.JList.class;
0069         * for(Class cls = rootClass; cls != null; cls = cls.getSuperclass()) {
0070         *     superClasses.addElement(cls);
0071         * }
0072         * JList myList = new JList(superClasses);
0073         * 
0074         * // The automatically created model is stored in JList's "model"
0075         * // property, which you can retrieve
0076         *
0077         * ListModel model = myList.getModel();
0078         * for(int i = 0; i < model.getSize(); i++) {
0079         *     System.out.println(model.getElementAt(i));
0080         * }
0081         * </pre>
0082         * <p>
0083         * A {@code ListModel} can be supplied directly to a {@code JList} by way of a
0084         * constructor or the {@code setModel} method. The contents need not be static -
0085         * the number of items, and the values of items can change over time. A correct
0086         * {@code ListModel} implementation notifies the set of
0087         * {@code javax.swing.event.ListDataListener}s that have been added to it, each
0088         * time a change occurs. These changes are characterized by a
0089         * {@code javax.swing.event.ListDataEvent}, which identifies the range of list
0090         * indices that have been modified, added, or removed. {@code JList}'s
0091         * {@code ListUI} is responsible for keeping the visual representation up to
0092         * date with changes, by listening to the model.
0093         * <p>
0094         * Simple, dynamic-content, {@code JList} applications can use the
0095         * {@code DefaultListModel} class to maintain list elements. This class
0096         * implements the {@code ListModel} interface and also provides a
0097         * <code>java.util.Vector</code>-like API. Applications that need a more
0098         * custom <code>ListModel</code> implementation may instead wish to subclass
0099         * {@code AbstractListModel}, which provides basic support for managing and
0100         * notifying listeners. For example, a read-only implementation of
0101         * {@code AbstractListModel}:
0102         * <pre>
0103         * // This list model has about 2^16 elements.  Enjoy scrolling.
0104         *
0105         * ListModel bigData = new AbstractListModel() {
0106         *     public int getSize() { return Short.MAX_VALUE; }
0107         *     public Object getElementAt(int index) { return "Index " + index; }
0108         * };
0109         * </pre>
0110         * <p>
0111         * The selection state of a {@code JList} is managed by another separate
0112         * model, an instance of {@code ListSelectionModel}. {@code JList} is
0113         * initialized with a selection model on construction, and also contains
0114         * methods to query or set this selection model. Additionally, {@code JList}
0115         * provides convenient methods for easily managing the selection. These methods,
0116         * such as {@code setSelectedIndex} and {@code getSelectedValue}, are cover
0117         * methods that take care of the details of interacting with the selection
0118         * model. By default, {@code JList}'s selection model is configured to allow any
0119         * combination of items to be selected at a time; selection mode
0120         * {@code MULTIPLE_INTERVAL_SELECTION}. The selection mode can be changed
0121         * on the selection model directly, or via {@code JList}'s cover method.
0122         * Responsibility for updating the selection model in response to user gestures
0123         * lies with the list's {@code ListUI}.
0124         * <p>
0125         * A correct {@code ListSelectionModel} implementation notifies the set of
0126         * {@code javax.swing.event.ListSelectionListener}s that have been added to it
0127         * each time a change to the selection occurs. These changes are characterized
0128         * by a {@code javax.swing.event.ListSelectionEvent}, which identifies the range
0129         * of the selection change.
0130         * <p>
0131         * The preferred way to listen for changes in list selection is to add
0132         * {@code ListSelectionListener}s directly to the {@code JList}. {@code JList}
0133         * then takes care of listening to the the selection model and notifying your
0134         * listeners of change.
0135         * <p>
0136         * Responsibility for listening to selection changes in order to keep the list's
0137         * visual representation up to date lies with the list's {@code ListUI}.
0138         * <p>
0139         * <a name="renderer">
0140         * Painting of cells in a {@code JList} is handled by a delegate called a
0141         * cell renderer, installed on the list as the {@code cellRenderer} property.
0142         * The renderer provides a {@code java.awt.Component} that is used
0143         * like a "rubber stamp" to paint the cells. Each time a cell needs to be
0144         * painted, the list's {@code ListUI} asks the cell renderer for the component,
0145         * moves it into place, and has it paint the contents of the cell by way of its
0146         * {@code paint} method. A default cell renderer, which uses a {@code JLabel}
0147         * component to render, is installed by the lists's {@code ListUI}. You can
0148         * substitute your own renderer using code like this:
0149         * <pre>
0150         *  // Display an icon and a string for each object in the list.
0151         *
0152         * class MyCellRenderer extends JLabel implements ListCellRenderer {
0153         *     final static ImageIcon longIcon = new ImageIcon("long.gif");
0154         *     final static ImageIcon shortIcon = new ImageIcon("short.gif");
0155         *
0156         *     // This is the only method defined by ListCellRenderer.
0157         *     // We just reconfigure the JLabel each time we're called.
0158         *
0159         *     public Component getListCellRendererComponent(
0160         *       JList list,              // the list
0161         *       Object value,            // value to display
0162         *       int index,               // cell index
0163         *       boolean isSelected,      // is the cell selected
0164         *       boolean cellHasFocus)    // does the cell have focus
0165         *     {
0166         *         String s = value.toString();
0167         *         setText(s);
0168         *         setIcon((s.length() > 10) ? longIcon : shortIcon);
0169         *         if (isSelected) {
0170         *             setBackground(list.getSelectionBackground());
0171         *             setForeground(list.getSelectionForeground());
0172         *         } else {
0173         *             setBackground(list.getBackground());
0174         *             setForeground(list.getForeground());
0175         *         }
0176         *         setEnabled(list.isEnabled());
0177         *         setFont(list.getFont());
0178         *         setOpaque(true);
0179         *         return this;
0180         *     }
0181         * }
0182         *
0183         * myList.setCellRenderer(new MyCellRenderer());
0184         * </pre>
0185         * <p>
0186         * Another job for the cell renderer is in helping to determine sizing
0187         * information for the list. By default, the list's {@code ListUI} determines
0188         * the size of cells by asking the cell renderer for its preferred
0189         * size for each list item. This can be expensive for large lists of items.
0190         * To avoid these calculations, you can set a {@code fixedCellWidth} and
0191         * {@code fixedCellHeight} on the list, or have these values calculated
0192         * automatically based on a single prototype value:
0193         * <a name="prototype_example">
0194         * <pre>
0195         * JList bigDataList = new JList(bigData);
0196         *
0197         * // We don't want the JList implementation to compute the width
0198         * // or height of all of the list cells, so we give it a string
0199         * // that's as big as we'll need for any cell.  It uses this to
0200         * // compute values for the fixedCellWidth and fixedCellHeight
0201         * // properties.
0202         *
0203         * bigDataList.setPrototypeCellValue("Index 1234567890");
0204         * </pre>
0205         * <p>
0206         * {@code JList} doesn't implement scrolling directly. To create a list that
0207         * scrolls, make it the viewport view of a {@code JScrollPane}. For example:
0208         * <pre>
0209         * JScrollPane scrollPane = new JScrollPane(myList);
0210         *
0211         * // Or in two steps:
0212         * JScrollPane scrollPane = new JScrollPane();
0213         * scrollPane.getViewport().setView(myList);
0214         * </pre>
0215         * <p>
0216         * {@code JList} doesn't provide any special handling of double or triple
0217         * (or N) mouse clicks, but it's easy to add a {@code MouseListener} if you
0218         * wish to take action on these events. Use the {@code locationToIndex}
0219         * method to determine what cell was clicked. For example:
0220         * <pre>
0221         * MouseListener mouseListener = new MouseAdapter() {
0222         *     public void mouseClicked(MouseEvent e) {
0223         *         if (e.getClickCount() == 2) {
0224         *             int index = list.locationToIndex(e.getPoint());
0225         *             System.out.println("Double clicked on Item " + index);
0226         *          }
0227         *     }
0228         * };
0229         * list.addMouseListener(mouseListener);
0230         * </pre>
0231         * <p>
0232         * <strong>Warning:</strong> Swing is not thread safe. For more
0233         * information see <a
0234         * href="package-summary.html#threading">Swing's Threading
0235         * Policy</a>.
0236         * <p>
0237         * <strong>Warning:</strong>
0238         * Serialized objects of this class will not be compatible with
0239         * future Swing releases. The current serialization support is
0240         * appropriate for short term storage or RMI between applications running
0241         * the same version of Swing.  As of 1.4, support for long term storage
0242         * of all JavaBeans<sup><font size="-2">TM</font></sup>
0243         * has been added to the <code>java.beans</code> package.
0244         * Please see {@link java.beans.XMLEncoder}.
0245         * <p>
0246         * See <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/list.html">How to Use Lists</a>
0247         * in <a href="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
0248         * for further documentation.
0249         * Also see the article <a href="http://java.sun.com/products/jfc/tsc/tech_topics/jlist_1/jlist.html">Advanced JList Programming</a>
0250         * in <a href="http://java.sun.com/products/jfc/tsc"><em>The Swing Connection</em></a>.
0251         * <p>
0252         * @see ListModel
0253         * @see AbstractListModel
0254         * @see DefaultListModel
0255         * @see ListSelectionModel
0256         * @see DefaultListSelectionModel
0257         * @see ListCellRenderer
0258         * @see DefaultListCellRenderer
0259         *
0260         * @beaninfo
0261         *   attribute: isContainer false
0262         * description: A component which allows for the selection of one or more objects from a list.
0263         *
0264         * @version 1.142 05/05/07
0265         * @author Hans Muller
0266         */
0267        public class JList extends JComponent implements  Scrollable, Accessible {
0268            /**
0269             * @see #getUIClassID
0270             * @see #readObject
0271             */
0272            private static final String uiClassID = "ListUI";
0273
0274            /** 
0275             * Indicates a vertical layout of cells, in a single column;
0276             * the default layout.
0277             * @see #setLayoutOrientation
0278             * @since 1.4
0279             */
0280            public static final int VERTICAL = 0;
0281
0282            /** 
0283             * Indicates a "newspaper style" layout with cells flowing vertically
0284             * then horizontally.
0285             * @see #setLayoutOrientation
0286             * @since 1.4
0287             */
0288            public static final int VERTICAL_WRAP = 1;
0289
0290            /** 
0291             * Indicates a "newspaper style" layout with cells flowing horizontally
0292             * then vertically.
0293             * @see #setLayoutOrientation
0294             * @since 1.4
0295             */
0296            public static final int HORIZONTAL_WRAP = 2;
0297
0298            private int fixedCellWidth = -1;
0299            private int fixedCellHeight = -1;
0300            private int horizontalScrollIncrement = -1;
0301            private Object prototypeCellValue;
0302            private int visibleRowCount = 8;
0303            private Color selectionForeground;
0304            private Color selectionBackground;
0305            private boolean dragEnabled;
0306
0307            private ListSelectionModel selectionModel;
0308            private ListModel dataModel;
0309            private ListCellRenderer cellRenderer;
0310            private ListSelectionListener selectionListener;
0311
0312            /**
0313             * How to lay out the cells; defaults to <code>VERTICAL</code>.
0314             */
0315            private int layoutOrientation;
0316
0317            /**
0318             * The drop mode for this component.
0319             */
0320            private DropMode dropMode = DropMode.USE_SELECTION;
0321
0322            /**
0323             * The drop location.
0324             */
0325            private transient DropLocation dropLocation;
0326
0327            /**
0328             * A subclass of <code>TransferHandler.DropLocation</code> representing
0329             * a drop location for a <code>JList</code>.
0330             *
0331             * @see #getDropLocation
0332             * @since 1.6
0333             */
0334            public static final class DropLocation extends
0335                    TransferHandler.DropLocation {
0336                private final int index;
0337                private final boolean isInsert;
0338
0339                private DropLocation(Point p, int index, boolean isInsert) {
0340                    super (p);
0341                    this .index = index;
0342                    this .isInsert = isInsert;
0343                }
0344
0345                /**
0346                 * Returns the index where dropped data should be placed in the
0347                 * list. Interpretation of the value depends on the drop mode set on
0348                 * the associated component. If the drop mode is either
0349                 * <code>DropMode.USE_SELECTION</code> or <code>DropMode.ON</code>,
0350                 * the return value is an index of a row in the list. If the drop mode is
0351                 * <code>DropMode.INSERT</code>, the return value refers to the index
0352                 * where the data should be inserted. If the drop mode is
0353                 * <code>DropMode.ON_OR_INSERT</code>, the value of
0354                 * <code>isInsert()</code> indicates whether the index is an index
0355                 * of a row, or an insert index.
0356                 * <p>
0357                 * <code>-1</code> indicates that the drop occurred over empty space,
0358                 * and no index could be calculated.
0359                 *
0360                 * @return the drop index
0361                 */
0362                public int getIndex() {
0363                    return index;
0364                }
0365
0366                /**
0367                 * Returns whether or not this location represents an insert
0368                 * location.
0369                 *
0370                 * @return whether or not this is an insert location
0371                 */
0372                public boolean isInsert() {
0373                    return isInsert;
0374                }
0375
0376                /**
0377                 * Returns a string representation of this drop location.
0378                 * This method is intended to be used for debugging purposes,
0379                 * and the content and format of the returned string may vary
0380                 * between implementations.
0381                 *
0382                 * @return a string representation of this drop location
0383                 */
0384                public String toString() {
0385                    return getClass().getName() + "[dropPoint="
0386                            + getDropPoint() + "," + "index=" + index + ","
0387                            + "insert=" + isInsert + "]";
0388                }
0389            }
0390
0391            /**
0392             * Constructs a {@code JList} that displays elements from the specified,
0393             * {@code non-null}, model. All {@code JList} constructors delegate to
0394             * this one.
0395             * <p>
0396             * This constructor registers the list with the {@code ToolTipManager},
0397             * allowing for tooltips to be provided by the cell renderers.
0398             *
0399             * @param dataModel the model for the list
0400             * @exception IllegalArgumentException if the model is {@code null}
0401             */
0402            public JList(ListModel dataModel) {
0403                if (dataModel == null) {
0404                    throw new IllegalArgumentException(
0405                            "dataModel must be non null");
0406                }
0407
0408                // Register with the ToolTipManager so that tooltips from the
0409                // renderer show through.
0410                ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
0411                toolTipManager.registerComponent(this );
0412
0413                layoutOrientation = VERTICAL;
0414
0415                this .dataModel = dataModel;
0416                selectionModel = createSelectionModel();
0417                setAutoscrolls(true);
0418                setOpaque(true);
0419                updateUI();
0420            }
0421
0422            /**
0423             * Constructs a <code>JList</code> that displays the elements in
0424             * the specified array. This constructor creates a read-only model
0425             * for the given array, and then delegates to the constructor that
0426             * takes a {@code ListModel}.
0427             * <p>
0428             * Attempts to pass a {@code null} value to this method results in
0429             * undefined behavior and, most likely, exceptions. The created model
0430             * references the given array directly. Attempts to modify the array
0431             * after constructing the list results in undefined behavior.
0432             *
0433             * @param  listData  the array of Objects to be loaded into the data model,
0434             *                   {@code non-null}
0435             */
0436            public JList(final Object[] listData) {
0437                this (new AbstractListModel() {
0438                    public int getSize() {
0439                        return listData.length;
0440                    }
0441
0442                    public Object getElementAt(int i) {
0443                        return listData[i];
0444                    }
0445                });
0446            }
0447
0448            /**
0449             * Constructs a <code>JList</code> that displays the elements in
0450             * the specified <code>Vector</code>. This constructor creates a read-only
0451             * model for the given {@code Vector}, and then delegates to the constructor
0452             * that takes a {@code ListModel}.
0453             * <p>
0454             * Attempts to pass a {@code null} value to this method results in
0455             * undefined behavior and, most likely, exceptions. The created model
0456             * references the given {@code Vector} directly. Attempts to modify the
0457             * {@code Vector} after constructing the list results in undefined behavior.
0458             *
0459             * @param  listData  the <code>Vector</code> to be loaded into the
0460             *		         data model, {@code non-null}
0461             */
0462            public JList(final Vector<?> listData) {
0463                this (new AbstractListModel() {
0464                    public int getSize() {
0465                        return listData.size();
0466                    }
0467
0468                    public Object getElementAt(int i) {
0469                        return listData.elementAt(i);
0470                    }
0471                });
0472            }
0473
0474            /**
0475             * Constructs a <code>JList</code> with an empty, read-only, model.
0476             */
0477            public JList() {
0478                this (new AbstractListModel() {
0479                    public int getSize() {
0480                        return 0;
0481                    }
0482
0483                    public Object getElementAt(int i) {
0484                        return "No Data Model";
0485                    }
0486                });
0487            }
0488
0489            /**
0490             * Returns the {@code ListUI}, the look and feel object that
0491             * renders this component.
0492             *
0493             * @return the <code>ListUI</code> object that renders this component
0494             */
0495            public ListUI getUI() {
0496                return (ListUI) ui;
0497            }
0498
0499            /**
0500             * Sets the {@code ListUI}, the look and feel object that
0501             * renders this component.
0502             *
0503             * @param ui  the <code>ListUI</code> object
0504             * @see UIDefaults#getUI
0505             * @beaninfo
0506             *        bound: true
0507             *       hidden: true
0508             *    attribute: visualUpdate true
0509             *  description: The UI object that implements the Component's LookAndFeel. 
0510             */
0511            public void setUI(ListUI ui) {
0512                super .setUI(ui);
0513            }
0514
0515            /**
0516             * Resets the {@code ListUI} property by setting it to the value provided
0517             * by the current look and feel. If the current cell renderer was installed
0518             * by the developer (rather than the look and feel itself), this also causes
0519             * the cell renderer and its children to be updated, by calling
0520             * {@code SwingUtilities.updateComponentTreeUI} on it.
0521             *
0522             * @see UIManager#getUI
0523             * @see SwingUtilities#updateComponentTreeUI
0524             */
0525            public void updateUI() {
0526                setUI((ListUI) UIManager.getUI(this ));
0527
0528                ListCellRenderer renderer = getCellRenderer();
0529                if (renderer instanceof  Component) {
0530                    SwingUtilities.updateComponentTreeUI((Component) renderer);
0531                }
0532            }
0533
0534            /**
0535             * Returns {@code "ListUI"}, the <code>UIDefaults</code> key used to look
0536             * up the name of the {@code javax.swing.plaf.ListUI} class that defines
0537             * the look and feel for this component.
0538             *
0539             * @return the string "ListUI"
0540             * @see JComponent#getUIClassID
0541             * @see UIDefaults#getUI
0542             */
0543            public String getUIClassID() {
0544                return uiClassID;
0545            }
0546
0547            /* -----private-----
0548             * This method is called by setPrototypeCellValue and setCellRenderer
0549             * to update the fixedCellWidth and fixedCellHeight properties from the
0550             * current value of prototypeCellValue (if it's non null).
0551             * <p>
0552             * This method sets fixedCellWidth and fixedCellHeight but does <b>not</b>
0553             * generate PropertyChangeEvents for them.
0554             *
0555             * @see #setPrototypeCellValue
0556             * @see #setCellRenderer
0557             */
0558            private void updateFixedCellSize() {
0559                ListCellRenderer cr = getCellRenderer();
0560                Object value = getPrototypeCellValue();
0561
0562                if ((cr != null) && (value != null)) {
0563                    Component c = cr.getListCellRendererComponent(this , value,
0564                            0, false, false);
0565
0566                    /* The ListUI implementation will add Component c to its private
0567                     * CellRendererPane however we can't assume that's already
0568                     * been done here.  So we temporarily set the one "inherited"
0569                     * property that may affect the renderer components preferred size:
0570                     * its font.
0571                     */
0572                    Font f = c.getFont();
0573                    c.setFont(getFont());
0574
0575                    Dimension d = c.getPreferredSize();
0576                    fixedCellWidth = d.width;
0577                    fixedCellHeight = d.height;
0578
0579                    c.setFont(f);
0580                }
0581            }
0582
0583            /**
0584             * Returns the "prototypical" cell value -- a value used to calculate a
0585             * fixed width and height for cells. This can be {@code null} if there
0586             * is no such value.
0587             *
0588             * @return the value of the {@code prototypeCellValue} property
0589             * @see #setPrototypeCellValue
0590             */
0591            public Object getPrototypeCellValue() {
0592                return prototypeCellValue;
0593            }
0594
0595            /**
0596             * Sets the {@code prototypeCellValue} property, and then (if the new value
0597             * is {@code non-null}), computes the {@code fixedCellWidth} and
0598             * {@code fixedCellHeight} properties by requesting the cell renderer
0599             * component for the given value (and index 0) from the cell renderer, and
0600             * using that component's preferred size.
0601             * <p>
0602             * This method is useful when the list is too long to allow the
0603             * {@code ListUI} to compute the width/height of each cell, and there is a
0604             * single cell value that is known to occupy as much space as any of the
0605             * others, a so-called prototype.
0606             * <p>
0607             * While all three of the {@code prototypeCellValue},
0608             * {@code fixedCellHeight}, and {@code fixedCellWidth} properties may be
0609             * modified by this method, {@code PropertyChangeEvent} notifications are
0610             * only sent when the {@code prototypeCellValue} property changes.
0611             * <p>
0612             * To see an example which sets this property, see the
0613             * <a href="#prototype_example">class description</a> above.
0614             * <p>
0615             * The default value of this property is <code>null</code>.
0616             * <p>
0617             * This is a JavaBeans bound property.  
0618             *
0619             * @param prototypeCellValue  the value on which to base
0620             *				<code>fixedCellWidth</code> and
0621             * 				<code>fixedCellHeight</code>
0622             * @see #getPrototypeCellValue
0623             * @see #setFixedCellWidth
0624             * @see #setFixedCellHeight
0625             * @see JComponent#addPropertyChangeListener
0626             * @beaninfo
0627             *       bound: true
0628             *   attribute: visualUpdate true
0629             * description: The cell prototype value, used to compute cell width and height.
0630             */
0631            public void setPrototypeCellValue(Object prototypeCellValue) {
0632                Object oldValue = this .prototypeCellValue;
0633                this .prototypeCellValue = prototypeCellValue;
0634
0635                /* If the prototypeCellValue has changed and is non-null,
0636                 * then recompute fixedCellWidth and fixedCellHeight.
0637                 */
0638
0639                if ((prototypeCellValue != null)
0640                        && !prototypeCellValue.equals(oldValue)) {
0641                    updateFixedCellSize();
0642                }
0643
0644                firePropertyChange("prototypeCellValue", oldValue,
0645                        prototypeCellValue);
0646            }
0647
0648            /**
0649             * Returns the value of the {@code fixedCellWidth} property.
0650             *
0651             * @return the fixed cell width
0652             * @see #setFixedCellWidth
0653             */
0654            public int getFixedCellWidth() {
0655                return fixedCellWidth;
0656            }
0657
0658            /**
0659             * Sets a fixed value to be used for the width of every cell in the list.
0660             * If {@code width} is -1, cell widths are computed in the {@code ListUI}
0661             * by applying <code>getPreferredSize</code> to the cell renderer component
0662             * for each list element.
0663             * <p>
0664             * The default value of this property is {@code -1}.
0665             * <p>
0666             * This is a JavaBeans bound property.
0667             *
0668             * @param width the width to be used for all cells in the list
0669             * @see #setPrototypeCellValue
0670             * @see #setFixedCellWidth
0671             * @see JComponent#addPropertyChangeListener
0672             * @beaninfo
0673             *       bound: true
0674             *   attribute: visualUpdate true
0675             * description: Defines a fixed cell width when greater than zero.
0676             */
0677            public void setFixedCellWidth(int width) {
0678                int oldValue = fixedCellWidth;
0679                fixedCellWidth = width;
0680                firePropertyChange("fixedCellWidth", oldValue, fixedCellWidth);
0681            }
0682
0683            /**
0684             * Returns the value of the {@code fixedCellHeight} property.
0685             * 
0686             * @return the fixed cell height
0687             * @see #setFixedCellHeight
0688             */
0689            public int getFixedCellHeight() {
0690                return fixedCellHeight;
0691            }
0692
0693            /**
0694             * Sets a fixed value to be used for the height of every cell in the list.
0695             * If {@code height} is -1, cell heights are computed in the {@code ListUI}
0696             * by applying <code>getPreferredSize</code> to the cell renderer component
0697             * for each list element.
0698             * <p>
0699             * The default value of this property is {@code -1}.
0700             * <p>
0701             * This is a JavaBeans bound property.
0702             *
0703             * @param height the height to be used for for all cells in the list
0704             * @see #setPrototypeCellValue
0705             * @see #setFixedCellWidth
0706             * @see JComponent#addPropertyChangeListener
0707             * @beaninfo
0708             *       bound: true
0709             *   attribute: visualUpdate true
0710             * description: Defines a fixed cell height when greater than zero.
0711             */
0712            public void setFixedCellHeight(int height) {
0713                int oldValue = fixedCellHeight;
0714                fixedCellHeight = height;
0715                firePropertyChange("fixedCellHeight", oldValue, fixedCellHeight);
0716            }
0717
0718            /**
0719             * Returns the object responsible for painting list items.
0720             *
0721             * @return the value of the {@code cellRenderer} property
0722             * @see #setCellRenderer
0723             */
0724            public ListCellRenderer getCellRenderer() {
0725                return cellRenderer;
0726            }
0727
0728            /**
0729             * Sets the delegate that is used to paint each cell in the list.
0730             * The job of a cell renderer is discussed in detail in the
0731             * <a href="#renderer">class level documentation</a>.
0732             * <p>
0733             * If the {@code prototypeCellValue} property is {@code non-null},
0734             * setting the cell renderer also causes the {@code fixedCellWidth} and
0735             * {@code fixedCellHeight} properties to be re-calculated. Only one
0736             * <code>PropertyChangeEvent</code> is generated however -
0737             * for the <code>cellRenderer</code> property.
0738             * <p>
0739             * The default value of this property is provided by the {@code ListUI}
0740             * delegate, i.e. by the look and feel implementation.
0741             * <p>
0742             * This is a JavaBeans bound property.
0743             *
0744             * @param cellRenderer the <code>ListCellRenderer</code>
0745             * 				that paints list cells
0746             * @see #getCellRenderer
0747             * @beaninfo
0748             *       bound: true
0749             *   attribute: visualUpdate true
0750             * description: The component used to draw the cells.
0751             */
0752            public void setCellRenderer(ListCellRenderer cellRenderer) {
0753                ListCellRenderer oldValue = this .cellRenderer;
0754                this .cellRenderer = cellRenderer;
0755
0756                /* If the cellRenderer has changed and prototypeCellValue
0757                 * was set, then recompute fixedCellWidth and fixedCellHeight.
0758                 */
0759                if ((cellRenderer != null) && !cellRenderer.equals(oldValue)) {
0760                    updateFixedCellSize();
0761                }
0762
0763                firePropertyChange("cellRenderer", oldValue, cellRenderer);
0764            }
0765
0766            /**
0767             * Returns the color used to draw the foreground of selected items.
0768             * {@code DefaultListCellRenderer} uses this color to draw the foreground
0769             * of items in the selected state, as do the renderers installed by most
0770             * {@code ListUI} implementations.
0771             *
0772             * @return the color to draw the foreground of selected items
0773             * @see #setSelectionForeground
0774             * @see DefaultListCellRenderer
0775             */
0776            public Color getSelectionForeground() {
0777                return selectionForeground;
0778            }
0779
0780            /**
0781             * Sets the color used to draw the foreground of selected items, which
0782             * cell renderers can use to render text and graphics.
0783             * {@code DefaultListCellRenderer} uses this color to draw the foreground
0784             * of items in the selected state, as do the renderers installed by most
0785             * {@code ListUI} implementations.
0786             * <p>
0787             * The default value of this property is defined by the look and feel
0788             * implementation.
0789             * <p>
0790             * This is a JavaBeans bound property.
0791             *
0792             * @param selectionForeground  the {@code Color} to use in the foreground
0793             *                             for selected list items
0794             * @see #getSelectionForeground
0795             * @see #setSelectionBackground
0796             * @see #setForeground
0797             * @see #setBackground
0798             * @see #setFont
0799             * @see DefaultListCellRenderer
0800             * @beaninfo
0801             *       bound: true
0802             *   attribute: visualUpdate true
0803             * description: The foreground color of selected cells.
0804             */
0805            public void setSelectionForeground(Color selectionForeground) {
0806                Color oldValue = this .selectionForeground;
0807                this .selectionForeground = selectionForeground;
0808                firePropertyChange("selectionForeground", oldValue,
0809                        selectionForeground);
0810            }
0811
0812            /**
0813             * Returns the color used to draw the background of selected items.
0814             * {@code DefaultListCellRenderer} uses this color to draw the background
0815             * of items in the selected state, as do the renderers installed by most
0816             * {@code ListUI} implementations.
0817             *
0818             * @return the color to draw the background of selected items
0819             * @see #setSelectionBackground
0820             * @see DefaultListCellRenderer
0821             */
0822            public Color getSelectionBackground() {
0823                return selectionBackground;
0824            }
0825
0826            /**
0827             * Sets the color used to draw the background of selected items, which
0828             * cell renderers can use fill selected cells.
0829             * {@code DefaultListCellRenderer} uses this color to fill the background
0830             * of items in the selected state, as do the renderers installed by most
0831             * {@code ListUI} implementations.
0832             * <p>
0833             * The default value of this property is defined by the look
0834             * and feel implementation.
0835             * <p>
0836             * This is a JavaBeans bound property.
0837             *
0838             * @param selectionBackground  the {@code Color} to use for the 
0839             *                             background of selected cells
0840             * @see #getSelectionBackground
0841             * @see #setSelectionForeground
0842             * @see #setForeground
0843             * @see #setBackground
0844             * @see #setFont
0845             * @see DefaultListCellRenderer
0846             * @beaninfo
0847             *       bound: true
0848             *   attribute: visualUpdate true
0849             * description: The background color of selected cells.
0850             */
0851            public void setSelectionBackground(Color selectionBackground) {
0852                Color oldValue = this .selectionBackground;
0853                this .selectionBackground = selectionBackground;
0854                firePropertyChange("selectionBackground", oldValue,
0855                        selectionBackground);
0856            }
0857
0858            /**
0859             * Returns the value of the {@code visibleRowCount} property. See the
0860             * documentation for {@link #setVisibleRowCount} for details on how to
0861             * interpret this value.
0862             *
0863             * @return the value of the {@code visibleRowCount} property.
0864             * @see #setVisibleRowCount
0865             */
0866            public int getVisibleRowCount() {
0867                return visibleRowCount;
0868            }
0869
0870            /**
0871             * Sets the {@code visibleRowCount} property, which has different meanings
0872             * depending on the layout orientation: For a {@code VERTICAL} layout
0873             * orientation, this sets the preferred number of rows to display without
0874             * requiring scrolling; for other orientations, it affects the wrapping of
0875             * cells.
0876             * <p>
0877             * In {@code VERTICAL} orientation:<br>
0878             * Setting this property affects the return value of the
0879             * {@link #getPreferredScrollableViewportSize} method, which is used to
0880             * calculate the preferred size of an enclosing viewport. See that method's
0881             * documentation for more details.
0882             * <p>
0883             * In {@code HORIZONTAL_WRAP} and {@code VERTICAL_WRAP} orientations:<br>
0884             * This affects how cells are wrapped. See the documentation of
0885             * {@link #setLayoutOrientation} for more details.
0886             * <p>
0887             * The default value of this property is {@code 8}.
0888             * <p>
0889             * Calling this method with a negative value results in the property
0890             * being set to {@code 0}.
0891             * <p>
0892             * This is a JavaBeans bound property.
0893             *
0894             * @param visibleRowCount  an integer specifying the preferred number of
0895             *                         rows to display without requiring scrolling
0896             * @see #getVisibleRowCount
0897             * @see #getPreferredScrollableViewportSize
0898             * @see #setLayoutOrientation
0899             * @see JComponent#getVisibleRect
0900             * @see JViewport
0901             * @beaninfo
0902             *       bound: true
0903             *   attribute: visualUpdate true
0904             * description: The preferred number of rows to display without
0905             *              requiring scrolling
0906             */
0907            public void setVisibleRowCount(int visibleRowCount) {
0908                int oldValue = this .visibleRowCount;
0909                this .visibleRowCount = Math.max(0, visibleRowCount);
0910                firePropertyChange("visibleRowCount", oldValue, visibleRowCount);
0911            }
0912
0913            /**
0914             * Returns the layout orientation property for the list: {@code VERTICAL}
0915             * if the layout is a single column of cells, {@code VERTICAL_WRAP} if the
0916             * layout is "newspaper style" with the content flowing vertically then
0917             * horizontally, or {@code HORIZONTAL_WRAP} if the layout is "newspaper
0918             * style" with the content flowing horizontally then vertically.
0919             * 
0920             * @return the value of the {@code layoutOrientation} property
0921             * @see #setLayoutOrientation
0922             * @since 1.4
0923             */
0924            public int getLayoutOrientation() {
0925                return layoutOrientation;
0926            }
0927
0928            /**
0929             * Defines the way list cells are layed out. Consider a {@code JList}
0930             * with five cells. Cells can be layed out in one of the following ways:
0931             * <p>
0932             * <pre>
0933             * VERTICAL:          0
0934             *                    1
0935             *                    2
0936             *                    3
0937             *                    4
0938             *
0939             * HORIZONTAL_WRAP:   0  1  2
0940             *                    3  4
0941             *
0942             * VERTICAL_WRAP:     0  3
0943             *                    1  4
0944             *                    2
0945             * </pre>
0946             * <p>
0947             * A description of these layouts follows:
0948             *
0949             * <table border="1" 
0950             *  summary="Describes layouts VERTICAL, HORIZONTAL_WRAP, and VERTICAL_WRAP">
0951             *   <tr><th><p align="left">Value</p></th><th><p align="left">Description</p></th></tr>
0952             *   <tr><td><code>VERTICAL</code>
0953             *       <td>Cells are layed out vertically in a single column.
0954             *   <tr><td><code>HORIZONTAL_WRAP</code>
0955             *       <td>Cells are layed out horizontally, wrapping to a new row as
0956             *           necessary. If the {@code visibleRowCount} property is less than
0957             *           or equal to zero, wrapping is determined by the width of the
0958             *           list; otherwise wrapping is done in such a way as to ensure
0959             *           {@code visibleRowCount} rows in the list.
0960             *   <tr><td><code>VERTICAL_WRAP</code>
0961             *       <td>Cells are layed out vertically, wrapping to a new column as
0962             *           necessary. If the {@code visibleRowCount} property is less than
0963             *           or equal to zero, wrapping is determined by the height of the
0964             *           list; otherwise wrapping is done at {@code visibleRowCount} rows.
0965             *  </table>
0966             * <p>
0967             * The default value of this property is <code>VERTICAL</code>.
0968             *
0969             * @param layoutOrientation the new layout orientation, one of:
0970             *        {@code VERTICAL}, {@code HORIZONTAL_WRAP} or {@code VERTICAL_WRAP}
0971             * @see #getLayoutOrientation
0972             * @see #setVisibleRowCount
0973             * @see #getScrollableTracksViewportHeight
0974             * @see #getScrollableTracksViewportWidth
0975             * @throws IllegalArgumentException if {@code layoutOrientation} isn't one of the
0976             *         allowable values
0977             * @since 1.4
0978             * @beaninfo
0979             *       bound: true
0980             *   attribute: visualUpdate true
0981             * description: Defines the way list cells are layed out.
0982             *        enum: VERTICAL JList.VERTICAL 
0983             *              HORIZONTAL_WRAP JList.HORIZONTAL_WRAP
0984             *              VERTICAL_WRAP JList.VERTICAL_WRAP
0985             */
0986            public void setLayoutOrientation(int layoutOrientation) {
0987                int oldValue = this .layoutOrientation;
0988                switch (layoutOrientation) {
0989                case VERTICAL:
0990                case VERTICAL_WRAP:
0991                case HORIZONTAL_WRAP:
0992                    this .layoutOrientation = layoutOrientation;
0993                    firePropertyChange("layoutOrientation", oldValue,
0994                            layoutOrientation);
0995                    break;
0996                default:
0997                    throw new IllegalArgumentException(
0998                            "layoutOrientation must be one of: VERTICAL, HORIZONTAL_WRAP or VERTICAL_WRAP");
0999                }
1000            }
1001
1002            /**
1003             * Returns the smallest list index that is currently visible.
1004             * In a left-to-right {@code componentOrientation}, the first visible
1005             * cell is found closest to the list's upper-left corner. In right-to-left
1006             * orientation, it is found closest to the upper-right corner.
1007             * If nothing is visible or the list is empty, {@code -1} is returned.
1008             * Note that the returned cell may only be partially visible.
1009             *
1010             * @return the index of the first visible cell
1011             * @see #getLastVisibleIndex
1012             * @see JComponent#getVisibleRect
1013             */
1014            public int getFirstVisibleIndex() {
1015                Rectangle r = getVisibleRect();
1016                int first;
1017                if (this .getComponentOrientation().isLeftToRight()) {
1018                    first = locationToIndex(r.getLocation());
1019                } else {
1020                    first = locationToIndex(new Point((r.x + r.width) - 1, r.y));
1021                }
1022                if (first != -1) {
1023                    Rectangle bounds = getCellBounds(first, first);
1024                    if (bounds != null) {
1025                        SwingUtilities.computeIntersection(r.x, r.y, r.width,
1026                                r.height, bounds);
1027                        if (bounds.width == 0 || bounds.height == 0) {
1028                            first = -1;
1029                        }
1030                    }
1031                }
1032                return first;
1033            }
1034
1035            /**
1036             * Returns the largest list index that is currently visible.
1037             * If nothing is visible or the list is empty, {@code -1} is returned.
1038             * Note that the returned cell may only be partially visible.
1039             *
1040             * @return the index of the last visible cell
1041             * @see #getFirstVisibleIndex
1042             * @see JComponent#getVisibleRect
1043             */
1044            public int getLastVisibleIndex() {
1045                boolean leftToRight = this .getComponentOrientation()
1046                        .isLeftToRight();
1047                Rectangle r = getVisibleRect();
1048                Point lastPoint;
1049                if (leftToRight) {
1050                    lastPoint = new Point((r.x + r.width) - 1,
1051                            (r.y + r.height) - 1);
1052                } else {
1053                    lastPoint = new Point(r.x, (r.y + r.height) - 1);
1054                }
1055                int location = locationToIndex(lastPoint);
1056
1057                if (location != -1) {
1058                    Rectangle bounds = getCellBounds(location, location);
1059
1060                    if (bounds != null) {
1061                        SwingUtilities.computeIntersection(r.x, r.y, r.width,
1062                                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
1067                            // each cell for other list layout orientation.
1068                            boolean isHorizontalWrap = (getLayoutOrientation() == HORIZONTAL_WRAP);
1069                            Point visibleLocation = isHorizontalWrap ? new Point(
1070                                    lastPoint.x, r.y)
1071                                    : new Point(r.x, lastPoint.y);
1072                            int last;
1073                            int visIndex = -1;
1074                            int lIndex = location;
1075                            location = -1;
1076
1077                            do {
1078                                last = visIndex;
1079                                visIndex = locationToIndex(visibleLocation);
1080
1081                                if (visIndex != -1) {
1082                                    bounds = getCellBounds(visIndex, visIndex);
1083                                    if (visIndex != lIndex && bounds != null
1084                                            && bounds.contains(visibleLocation)) {
1085                                        location = visIndex;
1086                                        if (isHorizontalWrap) {
1087                                            visibleLocation.y = bounds.y
1088                                                    + bounds.height;
1089                                            if (visibleLocation.y >= lastPoint.y) {
1090                                                // Past visible region, bail.
1091                                                last = visIndex;
1092                                            }
1093                                        } else {
1094                                            visibleLocation.x = bounds.x
1095                                                    + bounds.width;
1096                                            if (visibleLocation.x >= lastPoint.x) {
1097                                                // Past visible region, bail.
1098                                                last = visIndex;
1099                                            }
1100                                        }
1101
1102                                    } else {
1103                                        last = visIndex;
1104                                    }
1105                                }
1106                            } while (visIndex != -1 && last != visIndex);
1107                        }
1108                    }
1109                }
1110                return location;
1111            }
1112
1113            /**
1114             * Scrolls the list within an enclosing viewport to make the specified
1115             * cell completely visible. This calls {@code scrollRectToVisible} with
1116             * the bounds of the specified cell. For this method to work, the
1117             * {@code JList} must be within a <code>JViewport</code>.
1118             * <p>
1119             * If the given index is outside the list's range of cells, this method
1120             * results in nothing.
1121             *
1122             * @param index  the index of the cell to make visible
1123             * @see JComponent#scrollRectToVisible
1124             * @see #getVisibleRect
1125             */
1126            public void ensureIndexIsVisible(int index) {
1127                Rectangle cellBounds = getCellBounds(index, index);
1128                if (cellBounds != null) {
1129                    scrollRectToVisible(cellBounds);
1130                }
1131            }
1132
1133            /**
1134             * Turns on or off automatic drag handling. In order to enable automatic
1135             * drag handling, this property should be set to {@code true}, and the
1136             * list's {@code TransferHandler} needs to be {@code non-null}.
1137             * The default value of the {@code dragEnabled} property is {@code false}.
1138             * <p>
1139             * The job of honoring this property, and recognizing a user drag gesture,
1140             * lies with the look and feel implementation, and in particular, the list's
1141             * {@code ListUI}. When automatic drag handling is enabled, most look and
1142             * feels (including those that subclass {@code BasicLookAndFeel}) begin a
1143             * drag and drop operation whenever the user presses the mouse button over
1144             * an item and then moves the mouse a few pixels. Setting this property to
1145             * {@code true} can therefore have a subtle effect on how selections behave.
1146             * <p>
1147             * If a look and feel is used that ignores this property, you can still
1148             * begin a drag and drop operation by calling {@code exportAsDrag} on the
1149             * list's {@code TransferHandler}.
1150             *
1151             * @param b whether or not to enable automatic drag handling
1152             * @exception HeadlessException if
1153             *            <code>b</code> is <code>true</code> and
1154             *            <code>GraphicsEnvironment.isHeadless()</code>
1155             *            returns <code>true</code>
1156             * @see java.awt.GraphicsEnvironment#isHeadless
1157             * @see #getDragEnabled
1158             * @see #setTransferHandler
1159             * @see TransferHandler
1160             * @since 1.4
1161             *
1162             * @beaninfo
1163             *  description: determines whether automatic drag handling is enabled
1164             *        bound: false
1165             */
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,
1186             * the default for this property is <code>DropMode.USE_SELECTION</code>.
1187             * Usage of one of the other modes is recommended, however, for an
1188             * improved user experience. <code>DropMode.ON</code>, for instance,
1189             * offers similar behavior of showing items as selected, but does so without
1190             * affecting the actual selection in the list.
1191             * <p>
1192             * <code>JList</code> supports the following drop modes:
1193             * <ul>
1194             *    <li><code>DropMode.USE_SELECTION</code></li>
1195             *    <li><code>DropMode.ON</code></li>
1196             *    <li><code>DropMode.INSERT</code></li>
1197             *    <li><code>DropMode.ON_OR_INSERT</code></li>
1198             * </ul>
1199             * The drop mode is only meaningful if this component has a
1200             * <code>TransferHandler</code> that accepts drops.
1201             *
1202             * @param dropMode the drop mode to use
1203             * @throws IllegalArgumentException if the drop mode is unsupported
1204             *         or <code>null</code>
1205             * @see #getDropMode
1206             * @see #getDropLocation
1207             * @see #setTransferHandler
1208             * @see TransferHandler
1209             * @since 1.6
1210             */
1211            public final void setDropMode(DropMode dropMode) {
1212                if (dropMode != null) {
1213                    switch (dropMode) {
1214                    case USE_SELECTION:
1215                    case ON:
1216                    case INSERT:
1217                    case ON_OR_INSERT:
1218                        this .dropMode = dropMode;
1219                        return;
1220                    }
1221                }
1222
1223                throw new IllegalArgumentException(dropMode
1224                        + ": Unsupported drop mode for list");
1225            }
1226
1227            /**
1228             * Returns the drop mode for this component.
1229             *
1230             * @return the drop mode for this component
1231             * @see #setDropMode
1232             * @since 1.6
1233             */
1234            public final DropMode getDropMode() {
1235                return dropMode;
1236            }
1237
1238            /**
1239             * Calculates a drop location in this component, representing where a
1240             * drop at the given point should insert data.
1241             *
1242             * @param p the point to calculate a drop location for
1243             * @return the drop location, or <code>null</code>
1244             */
1245            DropLocation dropLocationForPoint(Point p) {
1246                DropLocation location = null;
1247                Rectangle rect = null;
1248
1249                int index = locationToIndex(p);
1250                if (index != -1) {
1251                    rect = getCellBounds(index, index);
1252                }
1253
1254                switch (dropMode) {
1255                case USE_SELECTION:
1256                case ON:
1257                    location = new DropLocation(p, (rect != null && rect
1258                            .contains(p)) ? index : -1, false);
1259
1260                    break;
1261                case INSERT:
1262                    if (index == -1) {
1263                        location = new DropLocation(p, getModel().getSize(),
1264                                true);
1265                        break;
1266                    }
1267
1268                    if (layoutOrientation == HORIZONTAL_WRAP) {
1269                        boolean ltr = getComponentOrientation().isLeftToRight();
1270
1271                        if (SwingUtilities2.liesInHorizontal(rect, p, ltr,
1272                                false) == TRAILING) {
1273                            index++;
1274                            // special case for below all cells
1275                        } else if (index == getModel().getSize() - 1
1276                                && p.y >= rect.y + rect.height) {
1277                            index++;
1278                        }
1279                    } else {
1280                        if (SwingUtilities2.liesInVertical(rect, p, false) == TRAILING) {
1281                            index++;
1282                        }
1283                    }
1284
1285                    location = new DropLocation(p, index, true);
1286
1287                    break;
1288                case ON_OR_INSERT:
1289                    if (index == -1) {
1290                        location = new DropLocation(p, getModel().getSize(),
1291                                true);
1292                        break;
1293                    }
1294
1295                    boolean between = false;
1296
1297                    if (layoutOrientation == HORIZONTAL_WRAP) {
1298                        boolean ltr = getComponentOrientation().isLeftToRight();
1299
1300                        Section section = SwingUtilities2.liesInHorizontal(
1301                                rect, p, ltr, true);
1302                        if (section == TRAILING) {
1303                            index++;
1304                            between = true;
1305                            // special case for below all cells
1306                        } else if (index == getModel().getSize() - 1
1307                                && p.y >= rect.y + rect.height) {
1308                            index++;
1309                            between = true;
1310                        } else if (section == LEADING) {
1311                            between = true;
1312                        }
1313                    } else {
1314                        Section section = SwingUtilities2.liesInVertical(rect,
1315                                p, true);
1316                        if (section == LEADING) {
1317                            between = true;
1318                        } else if (section == TRAILING) {
1319                            index++;
1320                            between = true;
1321                        }
1322                    }
1323
1324                    location = new DropLocation(p, index, between);
1325
1326                    break;
1327                default:
1328                    assert false : "Unexpected drop mode";
1329                }
1330
1331                return location;
1332            }
1333
1334            /**
1335             * Called to set or clear the drop location during a DnD operation.
1336             * In some cases, the component may need to use it's internal selection
1337             * temporarily to indicate the drop location. To help facilitate this,
1338             * this method returns and accepts as a parameter a state object.
1339             * This state object can be used to store, and later restore, the selection
1340             * state. Whatever this method returns will be passed back to it in
1341             * future calls, as the state parameter. If it wants the DnD system to
1342             * continue storing the same state, it must pass it back every time.
1343             * Here's how this is used:
1344             * <p>
1345             * Let's say that on the first call to this method the component decides
1346             * to save some state (because it is about to use the selection to show
1347             * a drop index). It can return a state object to the caller encapsulating
1348             * any saved selection state. On a second call, let's say the drop location
1349             * is being changed to something else. The component doesn't need to
1350             * restore anything yet, so it simply passes back the same state object
1351             * to have the DnD system continue storing it. Finally, let's say this
1352             * method is messaged with <code>null</code>. This means DnD
1353             * is finished with this component for now, meaning it should restore
1354             * state. At this point, it can use the state parameter to restore
1355             * said state, and of course return <code>null</code> since there's
1356             * no longer anything to store.
1357             *
1358             * @param location the drop location (as calculated by
1359             *        <code>dropLocationForPoint</code>) or <code>null</code>
1360             *        if there's no longer a valid drop location
1361             * @param state the state object saved earlier for this component,
1362             *        or <code>null</code>
1363             * @param forDrop whether or not the method is being called because an
1364             *        actual drop occurred
1365             * @return any saved state for this component, or <code>null</code> if none
1366             */
1367            Object setDropLocation(TransferHandler.DropLocation location,
1368                    Object state, boolean forDrop) {
1369
1370                Object retVal = null;
1371                DropLocation listLocation = (DropLocation) location;
1372
1373                if (dropMode == DropMode.USE_SELECTION) {
1374                    if (listLocation == null) {
1375                        if (!forDrop && state != null) {
1376                            setSelectedIndices(((int[][]) state)[0]);
1377
1378                            int anchor = ((int[][]) state)[1][0];
1379                            int lead = ((int[][]) state)[1][1];
1380
1381                            SwingUtilities2.setLeadAnchorWithoutSelection(
1382                                    getSelectionModel(), lead, anchor);
1383                        }
1384                    } else {
1385                        if (dropLocation == null) {
1386                            int[] inds = getSelectedIndices();
1387                            retVal = new int[][] {
1388                                    inds,
1389                                    { getAnchorSelectionIndex(),
1390                                            getLeadSelectionIndex() } };
1391                        } else {
1392                            retVal = state;
1393                        }
1394
1395                        int index = listLocation.getIndex();
1396                        if (index == -1) {
1397                            clearSelection();
1398                            getSelectionModel().setAnchorSelectionIndex(-1);
1399                            getSelectionModel().setLeadSelectionIndex(-1);
1400                        } else {
1401                            setSelectionInterval(index, index);
1402                        }
1403                    }
1404                }
1405
1406                DropLocation old = dropLocation;
1407                dropLocation = listLocation;
1408                firePropertyChange("dropLocation", old, dropLocation);
1409
1410                return retVal;
1411            }
1412
1413            /**
1414             * Returns the location that this component should visually indicate
1415             * as the drop location during a DnD operation over the component,
1416             * or {@code null} if no location is to currently be shown.
1417             * <p>
1418             * This method is not meant for querying the drop location
1419             * from a {@code TransferHandler}, as the drop location is only
1420             * set after the {@code TransferHandler}'s <code>canImport</code>
1421             * has returned and has allowed for the location to be shown.
1422             * <p>
1423             * When this property changes, a property change event with
1424             * name "dropLocation" is fired by the component.
1425             * <p>
1426             * By default, responsibility for listening for changes to this property
1427             * and indicating the drop location visually lies with the list's
1428             * {@code ListUI}, which may paint it directly and/or install a cell
1429             * renderer to do so. Developers wishing to implement custom drop location
1430             * painting and/or replace the default cell renderer, may need to honor
1431             * this property.
1432             *
1433             * @return the drop location
1434             * @see #setDropMode
1435             * @see TransferHandler#canImport(TransferHandler.TransferSupport)
1436             * @since 1.6
1437             */
1438            public final DropLocation getDropLocation() {
1439                return dropLocation;
1440            }
1441
1442            /**
1443             * Returns the next list element whose {@code toString} value
1444             * starts with the given prefix.
1445             *
1446             * @param prefix the string to test for a match
1447             * @param startIndex the index for starting the search
1448             * @param bias the search direction, either 
1449             * Position.Bias.Forward or Position.Bias.Backward.
1450             * @return the index of the next list element that
1451             * starts with the prefix; otherwise {@code -1}
1452             * @exception IllegalArgumentException if prefix is {@code null}
1453             * or startIndex is out of bounds
1454             * @since 1.4
1455             */
1456            public int getNextMatch(String prefix, int startIndex,
1457                    Position.Bias bias) {
1458                ListModel model = getModel();
1459                int max = model.getSize();
1460                if (prefix == null) {
1461                    throw new IllegalArgumentException();
1462                }
1463                if (startIndex < 0 || startIndex >= max) {
1464                    throw new IllegalArgumentException();
1465                }
1466                prefix = prefix.toUpperCase();
1467
1468                // start search from the next element after the selected element
1469                int increment = (bias == Position.Bias.Forward) ? 1 : -1;
1470                int index = startIndex;
1471                do {
1472                    Object o = model.getElementAt(index);
1473
1474                    if (o != null) {
1475                        String string;
1476
1477                        if (o instanceof  String) {
1478                            string = ((String) o).toUpperCase();
1479                        } else {
1480                            string = o.toString();
1481                            if (string != null) {
1482                                string = string.toUpperCase();
1483                            }
1484                        }
1485
1486                        if (string != null && string.startsWith(prefix)) {
1487                            return index;
1488                        }
1489                    }
1490                    index = (index + increment + max) % max;
1491                } while (index != startIndex);
1492                return -1;
1493            }
1494
1495            /**
1496             * Returns the tooltip text to be used for the given event. This overrides
1497             * {@code JComponent}'s {@code getToolTipText} to first check the cell
1498             * renderer component for the cell over which the event occurred, returning
1499             * its tooltip text, if any. This implementation allows you to specify
1500             * tooltip text on the cell level, by using {@code setToolTipText} on your
1501             * cell renderer component.
1502             * <p>
1503             * <bold>Note:</bold> For <code>JList</code> to properly display the
1504             * tooltips of its renderers in this manner, <code>JList</code> must be a
1505             * registered component with the <code>ToolTipManager</code>. This registration
1506             * is done automatically in the constructor. However, if at a later point
1507             * <code>JList</code> is unregistered, by way of a call to
1508             * {@code setToolTipText(null)}, tips from the renderers will no longer display.
1509             *
1510             * @param event the {@code MouseEvent} to fetch the tooltip text for
1511             * @see JComponent#setToolTipText
1512             * @see JComponent#getToolTipText
1513             */
1514            public String getToolTipText(MouseEvent event) {
1515                if (event != null) {
1516                    Point p = event.getPoint();
1517                    int index = locationToIndex(p);
1518                    ListCellRenderer r = getCellRenderer();
1519                    Rectangle cellBounds;
1520
1521                    if (index != -1
1522                            && r != null
1523                            && (cellBounds = getCellBounds(index, index)) != null
1524                            && cellBounds.contains(p.x, p.y)) {
1525                        ListSelectionModel lsm = getSelectionModel();
1526                        Component rComponent = r.getListCellRendererComponent(
1527                                this , getModel().getElementAt(index), index,
1528                                lsm.isSelectedIndex(index), (hasFocus() && (lsm
1529                                        .getLeadSelectionIndex() == index)));
1530
1531                        if (rComponent instanceof  JComponent) {
1532                            MouseEvent newEvent;
1533
1534                            p.translate(-cellBounds.x, -cellBounds.y);
1535                            newEvent = new MouseEvent(rComponent,
1536                                    event.getID(), event.getWhen(), event
1537                                            .getModifiers(), p.x, p.y, event
1538                                            .getXOnScreen(), event
1539                                            .getYOnScreen(), event
1540                                            .getClickCount(), event
1541                                            .isPopupTrigger(),
1542                                    MouseEvent.NOBUTTON);
1543
1544                            String tip = ((JComponent) rComponent)
1545                                    .getToolTipText(newEvent);
1546
1547                            if (tip != null) {
1548                                return tip;
1549                            }
1550                        }
1551                    }
1552                }
1553                return super .getToolTipText();
1554            }
1555
1556            /**
1557             * --- ListUI Delegations ---
1558             */
1559
1560            /**
1561             * Returns the cell index closest to the given location in the list's
1562             * coordinate system. To determine if the cell actually contains the
1563             * specified location, compare the point against the cell's bounds,
1564             * as provided by {@code getCellBounds}. This method returns {@code -1}
1565             * if the model is empty
1566             * <p>
1567             * This is a cover method that delegates to the method of the same name
1568             * in the list's {@code ListUI}. It returns {@code -1} if the list has
1569             * no {@code ListUI}.
1570             *
1571             * @param location the coordinates of the point
1572             * @return the cell index closest to the given location, or {@code -1}
1573             */
1574            public int locationToIndex(Point location) {
1575                ListUI ui = getUI();
1576                return (ui != null) ? ui.locationToIndex(this , location) : -1;
1577            }
1578
1579            /**
1580             * Returns the origin of the specified item in the list's coordinate
1581             * system. This method returns {@code null} if the index isn't valid.
1582             * <p>
1583             * This is a cover method that delegates to the method of the same name
1584             * in the list's {@code ListUI}. It returns {@code null} if the list has
1585             * no {@code ListUI}.
1586             *
1587             * @param index the cell index
1588             * @return the origin of the cell, or {@code null}
1589             */
1590            public Point indexToLocation(int index) {
1591                ListUI ui = getUI();
1592                return (ui != null) ? ui.indexToLocation(this , index) : null;
1593            }
1594
1595            /** 
1596             * Returns the bounding rectangle, in the list's coordinate system,
1597             * for the range of cells specified by the two indices.
1598             * These indices can be supplied in any order.
1599             * <p>
1600             * If the smaller index is outside the list's range of cells, this method
1601             * returns {@code null}. If the smaller index is valid, but the larger
1602             * index is outside the list's range, the bounds of just the first index
1603             * is returned. Otherwise, the bounds of the valid range is returned.
1604             * <p>
1605             * This is a cover method that delegates to the method of the same name
1606             * in the list's {@code ListUI}. It returns {@code null} if the list has
1607             * no {@code ListUI}.
1608             *
1609             * @param index0 the first index in the range
1610             * @param index1 the second index in the range
1611             * @return the bounding rectangle for the range of cells, or {@code null}
1612             */
1613            public Rectangle getCellBounds(int index0, int index1) {
1614                ListUI ui = getUI();
1615                return (ui != null) ? ui.getCellBounds(this , index0, index1)
1616                        : null;
1617            }
1618
1619            /**
1620             * --- ListModel Support ---
1621             */
1622
1623            /**
1624             * Returns the data model that holds the list of items displayed
1625             * by the <code>JList</code> component.
1626             *
1627             * @return the <code>ListModel</code> that provides the displayed
1628             *				list of items
1629             * @see #setModel
1630             */
1631            public ListModel getModel() {
1632                return dataModel;
1633            }
1634
1635            /**
1636             * Sets the model that represents the contents or "value" of the
1637             * list, notifies property change listeners, and then clears the
1638             * list's selection.
1639             * <p>
1640             * This is a JavaBeans bound property.
1641             *
1642             * @param model  the <code>ListModel</code> that provides the
1643             *						list of items for display
1644             * @exception IllegalArgumentException  if <code>model</code> is 
1645             *						<code>null</code>
1646             * @see #getModel
1647             * @see #clearSelection
1648             * @beaninfo
1649             *       bound: true
1650             *   attribute: visualUpdate true
1651             * description: The object that contains the data to be drawn by this JList.
1652             */
1653            public void setModel(ListModel model) {
1654                if (model == null) {
1655                    throw new IllegalArgumentException("model must be non null");
1656                }
1657                ListModel oldValue = dataModel;
1658                dataModel = model;
1659                firePropertyChange("model", oldValue, dataModel);
1660                clearSelection();
1661            }
1662
1663            /**
1664             * Constructs a read-only <code>ListModel</code> from an array of objects,
1665             * and calls {@code setModel} with this model.
1666             * <p>
1667             * Attempts to pass a {@code null} value to this method results in
1668             * undefined behavior and, most likely, exceptions. The created model
1669             * references the given array directly. Attempts to modify the array
1670             * after invoking this method results in undefined behavior.
1671             *
1672             * @param listData an array of {@code Objects} containing the items to
1673             *        display in the list
1674             * @see #setModel
1675             */
1676            public void setListData(final Object[] listData) {
1677                setModel(new AbstractListModel() {
1678                    public int getSize() {
1679                        return listData.length;
1680                    }
1681
1682                    public Object getElementAt(int i) {
1683                        return listData[i];
1684                    }
1685                });
1686            }
1687
1688            /**
1689             * Constructs a read-only <code>ListModel</code> from a <code>Vector</code>
1690             * and calls {@code setModel} with this model.
1691             * <p>
1692             * Attempts to pass a {@code null} value to this method results in
1693             * undefined behavior and, most likely, exceptions. The created model
1694             * references the given {@code Vector} directly. Attempts to modify the
1695             * {@code Vector} after invoking this method results in undefined behavior.
1696             *
1697             * @param listData a <code>Vector</code> containing the items to
1698             *						display in the list
1699             * @see #setModel
1700             */
1701            public void setListData(final Vector<?> listData) {
1702                setModel(new AbstractListModel() {
1703                    public int getSize() {
1704                        return listData.size();
1705                    }
1706
1707                    public Object getElementAt(int i) {
1708                        return listData.elementAt(i);
1709                    }
1710                });
1711            }
1712
1713            /**
1714             * --- ListSelectionModel delegations and extensions ---
1715             */
1716
1717            /**
1718             * Returns an instance of {@code DefaultListSelectionModel}; called
1719             * during construction to initialize the list's selection model
1720             * property.
1721             *
1722             * @return a {@code DefaultListSelecitonModel}, used to initialize
1723             *         the list's selection model property during construction
1724             * @see #setSelectionModel
1725             * @see DefaultListSelectionModel
1726             */
1727            protected ListSelectionModel createSelectionModel() {
1728                return new DefaultListSelectionModel();
1729            }
1730
1731            /**
1732             * Returns the current selection model. The selection model maintains the
1733             * selection state of the list. See the class level documentation for more
1734             * details.
1735             *
1736             * @return the <code>ListSelectionModel</code> that maintains the
1737             *         list's selections
1738             *
1739             * @see #setSelectionModel
1740             * @see ListSelectionModel
1741             */
1742            public ListSelectionModel getSelectionModel() {
1743                return selectionModel;
1744            }
1745
1746            /**
1747             * Notifies {@code ListSelectionListener}s added directly to the list
1748             * of selection changes made to the selection model. {@code JList}
1749             * listens for changes made to the selection in the selection model,
1750             * and forwards notification to listeners added to the list directly,
1751             * by calling this method.
1752             * <p>
1753             * This method constructs a {@code ListSelectionEvent} with this list
1754             * as the source, and the specified arguments, and sends it to the
1755             * registered {@code ListSelectionListeners}.
1756             *
1757             * @param firstIndex the first index in the range, {@code <= lastIndex}
1758             * @param lastIndex the last index in the range, {@code >= firstIndex}
1759             * @param isAdjusting whether or not this is one in a series of
1760             *        multiple events, where changes are still being made
1761             *
1762             * @see #addListSelectionListener
1763             * @see #removeListSelectionListener
1764             * @see javax.swing.event.ListSelectionEvent
1765             * @see EventListenerList
1766             */
1767            protected void fireSelectionValueChanged(int firstIndex,
1768                    int lastIndex, boolean isAdjusting) {
1769                Object[] listeners = listenerList.getListenerList();
1770                ListSelectionEvent e = null;
1771
1772                for (int i = listeners.length - 2; i >= 0; i -= 2) {
1773                    if (listeners[i] == ListSelectionListener.class) {
1774                        if (e == null) {
1775                            e = new ListSelectionEvent(this , firstIndex,
1776                                    lastIndex, isAdjusting);
1777                        }
1778                        ((ListSelectionListener) listeners[i + 1])
1779                                .valueChanged(e);
1780                    }
1781                }
1782            }
1783
1784            /* A ListSelectionListener that forwards ListSelectionEvents from 
1785             * the selectionModel to the JList ListSelectionListeners.  The 
1786             * forwarded events only differ from the originals in that their 
1787             * source is the JList instead of the selectionModel itself.
1788             */
1789            private class ListSelectionHandler implements 
1790                    ListSelectionListener, Serializable {
1791                public void valueChanged(ListSelectionEvent e) {
1792                    fireSelectionValueChanged(e.getFirstIndex(), e
1793                            .getLastIndex(), e.getValueIsAdjusting());
1794                }
1795            }
1796
1797            /**
1798             * Adds a listener to the list, to be notified each time a change to the
1799             * selection occurs; the preferred way of listening for selection state
1800             * changes. {@code JList} takes care of listening for selection state
1801             * changes in the selection model, and notifies the given listener of
1802             * each change. {@code ListSelectionEvent}s sent to the listener have a
1803             * {@code source} property set to this list.
1804             *
1805             * @param listener the {@code ListSelectionListener} to add
1806             * @see #getSelectionModel
1807             * @see #getListSelectionListeners
1808             */
1809            public void addListSelectionListener(ListSelectionListener listener) {
1810                if (selectionListener == null) {
1811                    selectionListener = new ListSelectionHandler();
1812                    getSelectionModel().addListSelectionListener(
1813                            selectionListener);
1814                }
1815
1816                listenerList.add(ListSelectionListener.class, listener);
1817            }
1818
1819            /**
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(
1827                    ListSelectionListener listener) {
1828                listenerList.remove(ListSelectionListener.class, listener);
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            public ListSelectionListener[] getListSelectionListeners() {
1841                return (ListSelectionListener[]) listenerList
1842                        .getListeners(ListSelectionListener.class);
1843            }
1844
1845            /**
1846             * Sets the <code>selectionModel</code> for the list to a
1847             * non-<code>null</code> <code>ListSelectionModel</code>
1848             * implementation. The selection model handles the task of making single
1849             * selections, selections of contiguous ranges, and non-contiguous
1850             * selections.
1851             * <p>
1852             * This is a JavaBeans bound property.
1853             *
1854             * @param selectionModel  the <code>ListSelectionModel</code> that
1855             *				implements the selections
1856             * @exception IllegalArgumentException   if <code>selectionModel</code>
1857             * 						is <code>null</code>
1858             * @see #getSelectionModel
1859             * @beaninfo
1860             *       bound: true
1861             * description: The selection model, recording which cells are selected.
1862             */
1863            public void setSelectionModel(ListSelectionModel selectionModel) {
1864                if (selectionModel == null) {
1865                    throw new IllegalArgumentException(
1866                            "selectionModel must be non null");
1867                }
1868
1869                /* Remove the forwarding ListSelectionListener from the old
1870                 * selectionModel, and add it to the new one, if necessary.
1871                 */
1872                if (selectionListener != null) {
1873                    this .selectionModel
1874                            .removeListSelectionListener(selectionListener);
1875                    selectionModel.addListSelectionListener(selectionListener);
1876                }
1877
1878                ListSelectionModel oldValue = this .selectionModel;
1879                this .selectionModel = selectionModel;
1880                firePropertyChange("selectionModel", oldValue, selectionModel);
1881            }
1882
1883            /**
1884             * Sets the selection mode for the list. This is a cover method that sets
1885             * the selection mode directly on the selection model.
1886             * <p>
1887             * The following list describes the accepted selection modes:
1888             * <ul>
1889             * <li>{@code ListSelectionModel.SINGLE_SELECTION} -
1890             *   Only one list index can be selected at a time. In this mode,
1891             *   {@code setSelectionInterval} and {@code addSelectionInterval} are
1892             *   equivalent, both replacing the current selection with the index
1893             *   represented by the second argument (the "lead").
1894             * <li>{@code ListSelectionModel.SINGLE_INTERVAL_SELECTION} -
1895             *   Only one contiguous interval can be selected at a time.
1896             *   In this mode, {@code addSelectionInterval} behaves like
1897             *   {@code setSelectionInterval} (replacing the current selection},
1898             *   unless the given interval is immediately adjacent to or overlaps
1899             *   the existing selection, and can be used to grow the selection.
1900             * <li>{@code ListSelectionModel.MULTIPLE_INTERVAL_SELECTION} -
1901             *   In this mode, there's no restriction on what can be selected.
1902             *   This mode is the default.
1903             * </ul>
1904             *
1905             * @param selectionMode the selection mode
1906             * @see #getSelectionMode
1907             * @throws IllegalArgumentException if the selection mode isn't
1908             *         one of those allowed
1909             * @beaninfo
1910             * description: The selection mode.
1911             *        enum: SINGLE_SELECTION            ListSelectionModel.SINGLE_SELECTION
1912             *              SINGLE_INTERVAL_SELECTION   ListSelectionModel.SINGLE_INTERVAL_SELECTION
1913             *              MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
1914             */
1915            public void setSelectionMode(int selectionMode) {
1916                getSelectionModel().setSelectionMode(selectionMode);
1917            }
1918
1919            /**
1920             * Returns the current selection mode for the list. This is a cover
1921             * method that delegates to the method of the same name on the
1922             * list's selection model.
1923             *
1924             * @return the current selection mode
1925             * @see #setSelectionMode
1926             */
1927            public int getSelectionMode() {
1928                return getSelectionModel().getSelectionMode();
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            public int getAnchorSelectionIndex() {
1939                return getSelectionModel().getAnchorSelectionIndex();
1940            }
1941
1942            /**
1943             * Returns the lead selection index. This is a cover method that
1944             * delegates to the method of the same name on the list's selection model.
1945             *
1946             * @return the lead selection index
1947             * @see ListSelectionModel#getLeadSelectionIndex
1948             * @beaninfo
1949             * description: The lead selection index.
1950             */
1951            public int getLeadSelectionIndex() {
1952                return getSelectionModel().getLeadSelectionIndex();
1953            }
1954
1955            /**
1956             * Returns the smallest selected cell index, or {@code -1} if the selection
1957             * is empty. This is a cover method that delegates to the method of the same
1958             * name on the list's selection model.
1959             *
1960             * @return the smallest selected cell index, or {@code -1}
1961             * @see ListSelectionModel#getMinSelectionIndex
1962             */
1963            public int getMinSelectionIndex() {
1964                return getSelectionModel().getMinSelectionIndex();
1965            }
1966
1967            /**
1968             * Returns the largest selected cell index, or {@code -1} if the selection
1969             * is empty. This is a cover method that delegates to the method of the same
1970             * name on the list's selection model.
1971             *
1972             * @return the largest selected cell index
1973             * @see ListSelectionModel#getMaxSelectionIndex
1974             */
1975            public int getMaxSelectionIndex() {
1976                return getSelectionModel().getMaxSelectionIndex();
1977            }
1978
1979            /**
1980             * Returns {@code true} if the specified index is selected,
1981             * else {@code false}. This is a cover method that delegates to the method
1982             * of the same name on the list's selection model.
1983             *
1984             * @param index index to be queried for selection state
1985             * @return {@code true} if the specified index is selected,
1986             *         else {@code false}
1987             * @see ListSelectionModel#isSelectedIndex
1988             * @see #setSelectedIndex
1989             */
1990            public boolean isSelectedIndex(int index) {
1991                return getSelectionModel().isSelectedIndex(index);
1992            }
1993
1994            /**
1995             * Returns {@code true} if nothing is selected, else {@code false}.
1996             * This is a cover method that delegates to the method of the same
1997             * name on the list's selection model.
1998             *
1999             * @return {@code true} if nothing is selected, else {@code false}
2000             * @see ListSelectionModel#isSelectionEmpty
2001             * @see #clearSelection
2002             */
2003            public boolean isSelectionEmpty() {
2004                return getSelectionModel().isSelectionEmpty();
2005            }
2006
2007            /**
2008             * Clears the selection; after calling this method, {@code isSelectionEmpty}
2009             * will return {@code true}. This is a cover method that delegates to the
2010             * method of the same name on the list's selection model.
2011             *
2012             * @see ListSelectionModel#clearSelection
2013             * @see #isSelectionEmpty
2014             */
2015            public void clearSelection() {
2016                getSelectionModel().clearSelection();
2017            }
2018
2019            /**
2020             * Selects the specified interval. Both {@code anchor} and {@code lead}
2021             * indices are included. {@code anchor} doesn't have to be less than or
2022             * equal to {@code lead}. This is a cover method that delegates to the
2023             * method of the same name on the list's selection model.
2024             * <p>
2025             * Refer to the documentation of the selection model class being used
2026             * for details on how values less than {@code 0} are handled.
2027             *
2028             * @param anchor the first index to select
2029             * @param lead the last index to select
2030             * @see ListSelectionModel#setSelectionInterval
2031             * @see DefaultListSelectionModel#setSelectionInterval
2032             * @see #createSelectionModel
2033             * @see #addSelectionInterval
2034             * @see #removeSelectionInterval
2035             */
2036            public void setSelectionInterval(int anchor, int lead) {
2037                getSelectionModel().setSelectionInterval(anchor, lead);
2038            }
2039
2040            /**
2041             * Sets the selection to be the union of the specified interval with current
2042             * selection. Both the {@code anchor} and {@code lead} indices are
2043             * included. {@code anchor} doesn't have to be less than or
2044             * equal to {@code lead}. This is a cover method that delegates to the
2045             * method of the same name on the list's selection model.
2046             * <p>
2047             * Refer to the documentation of the selection model class being used
2048             * for details on how values less than {@code 0} are handled.
2049             *
2050             * @param anchor the first index to add to the selection
2051             * @param lead the last index to add to the selection
2052             * @see ListSelectionModel#addSelectionInterval
2053             * @see DefaultListSelectionModel#addSelectionInterval
2054             * @see #createSelectionModel
2055             * @see #setSelectionInterval
2056             * @see #removeSelectionInterval
2057             */
2058            public void addSelectionInterval(int anchor, int lead) {
2059                getSelectionModel().addSelectionInterval(anchor, lead);
2060            }
2061
2062            /**
2063             * Sets the selection to be the set difference of the specified interval
2064             * and the current selection. Both the {@code index0} and {@code index1}
2065             * indices are removed. {@code index0} doesn't have to be less than or
2066             * equal to {@code index1}. This is a cover method that delegates to the
2067             * method of the same name on the list's selection model.
2068             * <p>
2069             * Refer to the documentation of the selection model class being used
2070             * for details on how values less than {@code 0} are handled.
2071             *
2072             * @param index0 the first index to remove from the selection
2073             * @param index1 the last index to remove from the selection
2074             * @see ListSelectionModel#removeSelectionInterval
2075             * @see DefaultListSelectionModel#removeSelectionInterval
2076             * @see #createSelectionModel
2077             * @see #setSelectionInterval
2078             * @see #addSelectionInterval
2079             */
2080            public void removeSelectionInterval(int index0, int index1) {
2081                getSelectionModel().removeSelectionInterval(index0, index1);
2082            }
2083
2084            /**
2085             * Sets the selection model's {@code valueIsAdjusting} property. When
2086             * {@code true}, upcoming changes to selection should be considered part
2087             * of a single change. This property is used internally and developers
2088             * typically need not call this method. For example, when the model is being
2089             * updated in response to a user drag, the value of the property is set
2090             * to {@code true} when the drag is initiated and set to {@code false}
2091             * when the drag is finished. This allows listeners to update only
2092             * when a change has been finalized, rather than handling all of the
2093             * intermediate values.
2094             * <p>
2095             * You may want to use this directly if making a series of changes
2096             * that should be considered part of a single change.
2097             * <p>
2098             * This is a cover method that delegates to the method of the same name on
2099             * the list's selection model. See the documentation for
2100             * {@link javax.swing.ListSelectionModel#setValueIsAdjusting} for
2101             * more details.
2102             *
2103             * @param b the new value for the property
2104             * @see ListSelectionModel#setValueIsAdjusting
2105             * @see javax.swing.event.ListSelectionEvent#getValueIsAdjusting
2106             * @see #getValueIsAdjusting
2107             */
2108            public void setValueIsAdjusting(boolean b) {
2109                getSelectionModel().setValueIsAdjusting(b);
2110            }
2111
2112            /**
2113             * Returns the value of the selection model's {@code isAdjusting} property.
2114             * <p>
2115             * This is a cover method that delegates to the method of the same name on
2116             * the list's selection model.
2117             *
2118             * @return the value of the selection model's {@code isAdjusting} property.
2119             *
2120             * @see #setValueIsAdjusting
2121             * @see ListSelectionModel#getValueIsAdjusting
2122             */
2123            public boolean getValueIsAdjusting() {
2124                return getSelectionModel().getValueIsAdjusting();
2125            }
2126
2127            /**
2128             * Returns an array of all of the selected indices, in increasing
2129             * order.
2130             *
2131             * @return all of the selected indices, in increasing order,
2132             *         or an empty array if nothing is selected
2133             * @see #removeSelectionInterval
2134             * @see #addListSelectionListener
2135             */
2136            public int[] getSelectedIndices() {
2137                ListSelectionModel sm = getSelectionModel();
2138                int iMin = sm.getMinSelectionIndex();
2139                int iMax = sm.getMaxSelectionIndex();
2140
2141                if ((iMin < 0) || (iMax < 0)) {
2142                    return new int[0];
2143                }
2144
2145                int[] rvTmp = new int[1 + (iMax - iMin)];
2146                int n = 0;
2147                for (int i = iMin; i <= iMax; i++) {
2148                    if (sm.isSelectedIndex(i)) {
2149                        rvTmp[n++] = i;
2150                    }
2151                }
2152                int[] rv = new int[n];
2153                System.arraycopy(rvTmp, 0, rv, 0, n);
2154                return rv;
2155            }
2156
2157            /**
2158             * Selects a single cell. Does nothing if the given index is greater
2159             * than or equal to the model size. This is a convenience method that uses
2160             * {@code setSelectionInterval} on the selection model. Refer to the
2161             * documentation for the selection model class being used for details on
2162             * how values less than {@code 0} are handled.
2163             *
2164             * @param index the index of the cell to select
2165             * @see ListSelectionModel#setSelectionInterval
2166             * @see #isSelectedIndex
2167             * @see #addListSelectionListener
2168             * @beaninfo
2169             * description: The index of the selected cell.
2170             */
2171            public void setSelectedIndex(int index) {
2172                if (index >= getModel().getSize()) {
2173                    return;
2174                }
2175                getSelectionModel().setSelectionInterval(index, index);
2176            }
2177
2178            /**
2179             * Changes the selection to be the set of indices specified by the given
2180             * array. Indices greater than or equal to the model size are ignored.
2181             * This is a convenience method that clears the selection and then uses
2182             * {@code addSelectionInterval} on the selection model to add the indices.
2183             * Refer to the documentation of the selection model class being used for
2184             * details on how values less than {@code 0} are handled.
2185             *
2186             * @param indices an array of the indices of the cells to select,
2187             *                {@code non-null}
2188             * @see ListSelectionModel#addSelectionInterval
2189             * @see #isSelectedIndex
2190             * @see #addListSelectionListener
2191             * @throws NullPointerException if the given array is {@code null}
2192             */
2193            public void setSelectedIndices(int[] indices) {
2194                ListSelectionModel sm = getSelectionModel();
2195                sm.clearSelection();
2196                int size = getModel().getSize();
2197                for (int i = 0; i < indices.length; i++) {
2198                    if (indices[i] < size) {
2199                        sm.addSelectionInterval(indices[i], indices[i]);
2200                    }
2201                }
2202            }
2203
2204            /**
2205             * Returns an array of all the selected values, in increasing order based
2206             * on their indices in the list.
2207             *
2208             * @return the selected values, or an empty array if nothing is selected
2209             * @see #isSelectedIndex
2210             * @see #getModel
2211             * @see #addListSelectionListener
2212             */
2213            public Object[] getSelectedValues() {
2214                ListSelectionModel sm = getSelectionModel();
2215                ListModel dm = getModel();
2216
2217                int iMin = sm.getMinSelectionIndex();
2218                int iMax = sm.getMaxSelectionIndex();
2219
2220                if ((iMin < 0) || (iMax < 0)) {
2221                    return new Object[0];
2222                }
2223
2224                Object[] rvTmp = new Object[1 + (iMax - iMin)];
2225                int n = 0;
2226                for (int i = iMin; i <= iMax; i++) {
2227                    if (sm.isSelectedIndex(i)) {
2228                        rvTmp[n++] = dm.getElementAt(i);
2229                    }
2230                }
2231                Object[] rv = new Object[n];
2232                System.arraycopy(rvTmp, 0, rv, 0, n);
2233                return rv;
2234            }
2235
2236            /**
2237             * Returns the smallest selected cell index; <i>the selection</i> when only
2238             * a single item is selected in the list. When multiple items are selected,
2239             * it is simply the smallest selected index. Returns {@code -1} if there is
2240             * no selection.
2241             * <p>
2242             * This method is a cover that delegates to {@code getMinSelectionIndex}.
2243             *
2244             * @return the smallest selected cell index
2245             * @see #getMinSelectionIndex
2246             * @see #addListSelectionListener
2247             */
2248            public int getSelectedIndex() {
2249                return getMinSelectionIndex();
2250            }
2251
2252            /**
2253             * Returns the value for the smallest selected cell index;
2254             * <i>the selected value</i> when only a single item is selected in the
2255             * list. When multiple items are selected, it is simply the value for the
2256             * smallest selected index. Returns {@code null} if there is no selection.
2257             * <p>
2258             * This is a convenience method that simply returns the model value for
2259             * {@code getMinSelectionIndex}.
2260             *
2261             * @return the first selected value
2262             * @see #getMinSelectionIndex
2263             * @see #getModel
2264             * @see #addListSelectionListener
2265             */
2266            public Object getSelectedValue() {
2267                int i = getMinSelectionIndex();
2268                return (i == -1) ? null : getModel().getElementAt(i);
2269            }
2270
2271            /**
2272             * Selects the specified object from the list.
2273             *
2274             * @param anObject      the object to select     
2275             * @param shouldScroll  {@code true} if the list should scroll to display
2276             *                      the selected object, if one exists; otherwise {@code false}
2277             */
2278            public void setSelectedValue(Object anObject, boolean shouldScroll) {
2279                if (anObject == null)
2280                    setSelectedIndex(-1);
2281                else if (!anObject.equals(getSelectedValue())) {
2282                    int i, c;
2283                    ListModel dm = getModel();
2284                    for (i = 0, c = dm.getSize(); i < c; i++)
2285                        if (anObject.equals(dm.getElementAt(i))) {
2286                            setSelectedIndex(i);
2287                            if (shouldScroll)
2288                                ensureIndexIsVisible(i);
2289                            repaint();
2290                            /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
2291                            return;
2292                        }
2293                    setSelectedIndex(-1);
2294                }
2295                repaint();
2296                /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
2297            }
2298
2299            /**
2300             * --- The Scrollable Implementation ---
2301             */
2302
2303            private void checkScrollableParameters(Rectangle visibleRect,
2304                    int orientation) {
2305                if (visibleRect == null) {
2306                    throw new IllegalArgumentException(
2307                            "visibleRect must be non-null");
2308                }
2309                switch (orientation) {
2310                case SwingConstants.VERTICAL:
2311                case SwingConstants.HORIZONTAL:
2312                    break;
2313                default:
2314                    throw new IllegalArgumentException(
2315                            "orientation must be one of: VERTICAL, HORIZONTAL");
2316                }
2317            }
2318
2319            /**
2320             * Computes the size of viewport needed to display {@code visibleRowCount}
2321             * rows. The value returned by this method depends on the layout
2322             * orientation:
2323             * <p>
2324             * <b>{@code VERTICAL}:</b>
2325             * <br>
2326             * This is trivial if both {@code fixedCellWidth} and {@code fixedCellHeight}
2327             * have been set (either explicitly or by specifying a prototype cell value).
2328             * The width is simply the {@code fixedCellWidth} plus the list's horizontal
2329             * insets. The height is the {@code fixedCellHeight} multiplied by the
2330             * {@code visibleRowCount}, plus the list's vertical insets.
2331             * <p>
2332             * If either {@code fixedCellWidth} or {@code fixedCellHeight} haven't been
2333             * specified, heuristics are used. If the model is empty, the width is
2334             * the {@code fixedCellWidth}, if greater than {@code 0}, or a hard-coded
2335             * value of {@code 256}. The height is the {@code fixedCellHeight} multiplied
2336             * by {@code visibleRowCount}, if {@code fixedCellHeight} is greater than
2337             * {@code 0}, otherwise it is a hard-coded value of {@code 16} multiplied by
2338             * {@code visibleRowCount}.
2339             * <p>
2340             * If the model isn't empty, the width is the preferred size's width,
2341             * typically the width of the widest list element. The height is the
2342             * {@code fixedCellHeight} multiplied by the {@code visibleRowCount},
2343             * plus the list's vertical insets.
2344             * <p>
2345             * <b>{@code VERTICAL_WRAP} or {@code HORIZONTAL_WRAP}:</b>
2346             * <br>
2347             * This method simply returns the value from {@code getPreferredSize}.
2348             * The list's {@code ListUI} is expected to override {@code getPreferredSize}
2349             * to return an appropriate value.
2350             *
2351             * @return a dimension containing the size of the viewport needed
2352             *          to display {@code visibleRowCount} rows
2353             * @see #getPreferredScrollableViewportSize
2354             * @see #setPrototypeCellValue
2355             */
2356            public Dimension getPreferredScrollableViewportSize() {
2357                if (getLayoutOrientation() != VERTICAL) {
2358                    return getPreferredSize();
2359                }
2360                Insets insets = getInsets();
2361                int dx = insets.left + insets.right;
2362                int dy = insets.top + insets.bottom;
2363
2364                int visibleRowCount = getVisibleRowCount();
2365                int fixedCellWidth = getFixedCellWidth();
2366                int fixedCellHeight = getFixedCellHeight();
2367
2368                if ((fixedCellWidth > 0) && (fixedCellHeight > 0)) {
2369                    int width = fixedCellWidth + dx;
2370                    int height = (visibleRowCount * fixedCellHeight) + dy;
2371                    return new Dimension(width, height);
2372                } else if (getModel().getSize() > 0) {
2373                    int width = getPreferredSize().width;
2374                    int height;
2375                    Rectangle r = getCellBounds(0, 0);
2376                    if (r != null) {
2377                        height = (visibleRowCount * r.height) + dy;
2378                    } else {
2379                        // Will only happen if UI null, shouldn't matter what we return
2380                        height = 1;
2381                    }
2382                    return new Dimension(width, height);
2383                } else {
2384                    fixedCellWidth = (fixedCellWidth > 0) ? fixedCellWidth
2385                            : 256;
2386                    fixedCellHeight = (fixedCellHeight > 0) ? fixedCellHeight
2387                            : 16;
2388                    return new Dimension(fixedCellWidth, fixedCellHeight
2389                            * visibleRowCount);
2390                }
2391            }
2392
2393            /**
2394             * Returns the distance to scroll to expose the next or previous
2395             * row (for vertical scrolling) or column (for horizontal scrolling).
2396             * <p>
2397             * For horizontal scrolling, if the layout orientation is {@code VERTICAL},
2398             * then the list's font size is returned (or {@code 1} if the font is
2399             * {@code null}).
2400             *
2401             * @param visibleRect the view area visible within the viewport
2402             * @param orientation {@code SwingConstants.HORIZONTAL} or
2403             *                    {@code SwingConstants.VERTICAL}
2404             * @param direction less or equal to zero to scroll up/back,
2405             *                  greater than zero for down/forward
2406             * @return the "unit" increment for scrolling in the specified direction;
2407             *         always positive
2408             * @see #getScrollableBlockIncrement
2409             * @see Scrollable#getScrollableUnitIncrement
2410             * @throws IllegalArgumentException if {@code visibleRect} is {@code null}, or
2411             *         {@code orientation} isn't one of {@code SwingConstants.VERTICAL} or
2412             *         {@code SwingConstants.HORIZONTAL}
2413             */
2414            public int getScrollableUnitIncrement(Rectangle visibleRect,
2415                    int orientation, int direction) {
2416                checkScrollableParameters(visibleRect, orientation);
2417
2418                if (orientation == SwingConstants.VERTICAL) {
2419                    int row = locationToIndex(visibleRect.getLocation());
2420
2421                    if (row == -1) {
2422                        return 0;
2423                    } else {
2424                        /* Scroll Down */
2425                        if (direction > 0) {
2426                            Rectangle r = getCellBounds(row, row);
2427                            return (r == null) ? 0 : r.height
2428                                    - (visibleRect.y - r.y);
2429                        }
2430                        /* Scroll Up */
2431                        else {
2432                            Rectangle r = getCellBounds(row, row);
2433
2434                            /* The first row is completely visible and it's row 0.
2435                             * We're done.
2436                             */
2437                            if ((r.y == visibleRect.y) && (row == 0)) {
2438                                return 0;
2439                            }
2440                            /* The first row is completely visible, return the
2441                             * height of the previous row or 0 if the first row
2442                             * is the top row of the list.
2443                             */
2444                            else if (r.y == visibleRect.y) {
2445                                Point loc = r.getLocation();
2446                                loc.y--;
2447                                int prevIndex = locationToIndex(loc);
2448                                Rectangle prevR = getCellBounds(prevIndex,
2449                                        prevIndex);
2450
2451                                if (prevR == null || prevR.y >= r.y) {
2452                                    return 0;
2453                                }
2454                                return prevR.height;
2455                            }
2456                            /* The first row is partially visible, return the
2457                             * height of hidden part.
2458                             */
2459                            else {
2460                                return visibleRect.y - r.y;
2461                            }
2462                        }
2463                    }
2464                } else if (orientation == SwingConstants.HORIZONTAL
2465                        && getLayoutOrientation() != JList.VERTICAL) {
2466                    boolean leftToRight = getComponentOrientation()
2467                            .isLeftToRight();
2468                    int index;
2469                    Point leadingPoint;
2470
2471                    if (leftToRight) {
2472                        leadingPoint = visibleRect.getLocation();
2473                    } else {
2474                        leadingPoint = new Point(visibleRect.x
2475                                + visibleRect.width - 1, visibleRect.y);
2476                    }
2477                    index = locationToIndex(leadingPoint);
2478
2479                    if (index != -1) {
2480                        Rectangle cellBounds = getCellBounds(index, index);
2481                        if (cellBounds != null
2482                                && cellBounds.contains(leadingPoint)) {
2483                            int leadingVisibleEdge;
2484                            int leadingCellEdge;
2485
2486                            if (leftToRight) {
2487                                leadingVisibleEdge = visibleRect.x;
2488                                leadingCellEdge = cellBounds.x;
2489                            } else {
2490                                leadingVisibleEdge = visibleRect.x
2491                                        + visibleRect.width;
2492                                leadingCellEdge = cellBounds.x
2493                                        + cellBounds.width;
2494                            }
2495
2496                            if (leadingCellEdge != leadingVisibleEdge) {
2497                                if (direction < 0) {
2498                                    // Show remainder of leading cell
2499                                    return Math.abs(leadingVisibleEdge
2500                                            - leadingCellEdge);
2501
2502                                } else if (leftToRight) {
2503                                    // Hide rest of leading cell
2504                                    return leadingCellEdge + cellBounds.width
2505                                            - leadingVisibleEdge;
2506                                } else {
2507                                    // Hide rest of leading cell
2508                                    return leadingVisibleEdge - cellBounds.x;
2509                                }
2510                            }
2511                            // ASSUME: All cells are the same width
2512                            return cellBounds.width;
2513                        }
2514                    }
2515                }
2516                Font f = getFont();
2517                return (f != null) ? f.getSize() : 1;
2518            }
2519
2520            /**
2521             * Returns the distance to scroll to expose the next or previous block.
2522             * <p>
2523             * For vertical scrolling, the following rules are used:
2524             * <ul>
2525             * <li>if scrolling down, returns the distance to scroll so that the last
2526             * visible element becomes the first completely visible element
2527             * <li>if scrolling up, returns the distance to scroll so that the first
2528             * visible element becomes the last completely visible element
2529             * <li>returns {@code visibleRect.height} if the list is empty
2530             * </ul>
2531             * <p>
2532             * For horizontal scrolling, when the layout orientation is either
2533             * {@code VERTICAL_WRAP} or {@code HORIZONTAL_WRAP}:
2534             * <ul>
2535             * <li>if scrolling right, returns the distance to scroll so that the
2536             * last visible element becomes
2537             * the first completely visible element
2538             * <li>if scrolling left, returns the distance to scroll so that the first
2539             * visible element becomes the last completely visible element
2540             * <li>returns {@code visibleRect.width} if the list is empty
2541             * </ul>
2542             * <p>
2543             * For horizontal scrolling and {@code VERTICAL} orientation,
2544             * returns {@code visibleRect.width}.
2545             * <p>
2546             * Note that the value of {@code visibleRect} must be the equal to 
2547             * {@code this.getVisibleRect()}.
2548             *
2549             * @param visibleRect the view area visible within the viewport
2550             * @param orientation {@code SwingConstants.HORIZONTAL} or
2551             *                    {@code SwingConstants.VERTICAL}
2552             * @param direction less or equal to zero to scroll up/back,
2553             *                  greater than zero for down/forward
2554             * @return the "block" increment for scrolling in the specified direction;
2555             *         always positive
2556             * @see #getScrollableUnitIncrement
2557             * @see Scrollable#getScrollableBlockIncrement
2558             * @throws IllegalArgumentException if {@code visibleRect} is {@code null}, or
2559             *         {@code orientation} isn't one of {@code SwingConstants.VERTICAL} or
2560             *         {@code SwingConstants.HORIZONTAL}
2561             */
2562            public int getScrollableBlockIncrement(Rectangle visibleRect,
2563                    int orientation, int direction) {
2564                checkScrollableParameters(visibleRect, orientation);
2565                if (orientation == SwingConstants.VERTICAL) {
2566                    int inc = visibleRect.height;
2567                    /* Scroll Down */
2568                    if (direction > 0) {
2569                        // last cell is the lowest left cell
2570                        int last = locationToIndex(new Point(visibleRect.x,
2571                                visibleRect.y + visibleRect.height - 1));
2572                        if (last != -1) {
2573                            Rectangle lastRect = getCellBounds(last, last);
2574                            if (lastRect != null) {
2575                                inc = lastRect.y - visibleRect.y;
2576                                if ((inc == 0)
2577                                        && (last < getModel().getSize() - 1)) {
2578                                    inc = lastRect.height;
2579                                }
2580                            }
2581                        }
2582                    }
2583                    /* Scroll Up */
2584                    else {
2585                        int newFirst = locationToIndex(new Point(visibleRect.x,
2586                                visibleRect.y - visibleRect.height));
2587                        int first = getFirstVisibleIndex();
2588                        if (newFirst != -1) {
2589                            if (first == -1) {
2590                                first = locationToIndex(visibleRect
2591                                        .getLocation());
2592                            }
2593                            Rectangle newFirstRect = getCellBounds(newFirst,
2594                                    newFirst);
2595                            Rectangle firstRect = getCellBounds(first, first);
2596                            if ((newFirstRect != null) && (firstRect != null)) {
2597                                while ((newFirstRect.y + visibleRect.height < firstRect.y
2598                                        + firstRect.height)
2599                                        && (newFirstRect.y < firstRect.y)) {
2600                                    newFirst++;
2601                                    newFirstRect = getCellBounds(newFirst,
2602                                            newFirst);
2603                                }
2604                                inc = visibleRect.y - newFirstRect.y;
2605                                if ((inc <= 0) && (newFirstRect.y > 0)) {
2606                                    newFirst--;
2607                                    newFirstRect = getCellBounds(newFirst,
2608                                            newFirst);
2609                                    if (newFirstRect != null) {
2610                                        inc = visibleRect.y - newFirstRect.y;
2611                                    }
2612                                }
2613                            }
2614                        }
2615                    }
2616                    return inc;
2617                } else if (orientation == SwingConstants.HORIZONTAL
2618                        && getLayoutOrientation() != JList.VERTICAL) {
2619                    boolean leftToRight = getComponentOrientation()
2620                            .isLeftToRight();
2621                    int inc = visibleRect.width;
2622                    /* Scroll Right (in ltr mode) or Scroll Left (in rtl mode) */
2623                    if (direction > 0) {
2624                        // position is upper right if ltr, or upper left otherwise
2625                        int x = visibleRect.x
2626                                + (leftToRight ? (visibleRect.width - 1) : 0);
2627                        int last = locationToIndex(new Point(x, visibleRect.y));
2628
2629                        if (last != -1) {
2630                            Rectangle lastRect = getCellBounds(last, last);
2631                            if (lastRect != null) {
2632                                if (leftToRight) {
2633                                    inc = lastRect.x - visibleRect.x;
2634                                } else {
2635                                    inc = visibleRect.x + visibleRect.width
2636                                            - (lastRect.x + lastRect.width);
2637                                }
2638                                if (inc < 0) {
2639                                    inc += lastRect.width;
2640                                } else if ((inc == 0)
2641                                        && (last < getModel().getSize() - 1)) {
2642                                    inc = lastRect.width;
2643                                }
2644                            }
2645                        }
2646                    }
2647                    /* Scroll Left (in ltr mode) or Scroll Right (in rtl mode) */
2648                    else {
2649                        // position is upper left corner of the visibleRect shifted
2650                        // left by the visibleRect.width if ltr, or upper right shifted
2651                        // right by the visibleRect.width otherwise
2652                        int x = visibleRect.x
2653                                + (leftToRight ? -visibleRect.width
2654                                        : visibleRect.width - 1
2655                                                + visibleRect.width);
2656                        int first = locationToIndex(new Point(x, visibleRect.y));
2657
2658                        if (first != -1) {
2659                            Rectangle firstRect = getCellBounds(first, first);
2660                            if (firstRect != null) {
2661                                // the right of the first cell
2662                                int firstRight = firstRect.x + firstRect.width;
2663
2664                                if (leftToRight) {
2665                                    if ((firstRect.x < visibleRect.x
2666                                            - visibleRect.width)
2667                                            && (firstRight < visibleRect.x)) {
2668                                        inc = visibleRect.x - firstRight;
2669                                    } else {
2670                                        inc = visibleRect.x - firstRect.x;
2671                                    }
2672                                } else {
2673                                    int visibleRight = visibleRect.x
2674                                            + visibleRect.width;
2675
2676                                    if ((firstRight > visibleRight
2677                                            + visibleRect.width)
2678                                            && (firstRect.x > visibleRight)) {
2679                                        inc = firstRect.x - visibleRight;
2680                                    } else {
2681                                        inc = firstRight - visibleRight;
2682                                    }
2683                                }
2684                            }
2685                        }
2686                    }
2687                    return inc;
2688                }
2689                return visibleRect.width;
2690            }
2691
2692            /**
2693             * Returns {@code true} if this {@code JList} is displayed in a 
2694             * {@code JViewport} and the viewport is wider than the list's
2695             * preferred width, or if the layout orientation is {@code HORIZONTAL_WRAP}
2696             * and {@code visibleRowCount <= 0}; otherwise returns {@code false}.
2697             * <p>
2698             * If {@code false}, then don't track the viewport's width. This allows
2699             * horizontal scrolling if the {@code JViewport} is itself embedded in a
2700             * {@code JScrollPane}.
2701             *
2702             * @return whether or not an enclosing viewport should force the list's
2703             *         width to match its own
2704             * @see Scrollable#getScrollableTracksViewportWidth
2705             */
2706            public boolean getScrollableTracksViewportWidth() {
2707                if (getLayoutOrientation() == HORIZONTAL_WRAP
2708                        && getVisibleRowCount() <= 0) {
2709                    return true;
2710                }
2711                if (getParent() instanceof  JViewport) {
2712                    return (((JViewport) getParent()).getWidth() > getPreferredSize().width);
2713                }
2714                return false;
2715            }
2716
2717            /**
2718             * Returns {@code true} if this {@code JList} is displayed in a 
2719             * {@code JViewport} and the viewport is taller than the list's
2720             * preferred height, or if the layout orientation is {@code VERTICAL_WRAP}
2721             * and {@code visibleRowCount <= 0}; otherwise returns {@code false}.
2722             * <p>
2723             * If {@code false}, then don't track the viewport's height. This allows
2724             * vertical scrolling if the {@code JViewport} is itself embedded in a
2725             * {@code JScrollPane}.
2726             *
2727             * @return whether or not an enclosing viewport should force the list's
2728             *         height to match its own
2729             * @see Scrollable#getScrollableTracksViewportHeight
2730             */
2731            public boolean getScrollableTracksViewportHeight() {
2732                if (getLayoutOrientation() == VERTICAL_WRAP
2733                        && getVisibleRowCount() <= 0) {
2734                    return true;
2735                }
2736                if (getParent() instanceof  JViewport) {
2737                    return (((JViewport) getParent()).getHeight() > getPreferredSize().height);
2738                }
2739                return false;
2740            }
2741
2742            /*
2743             * See {@code readObject} and {@code writeObject} in {@code JComponent}
2744             * for more information about serialization in Swing.
2745             */
2746            private void writeObject(ObjectOutputStream s) throws IOException {
2747                s.defaultWriteObject();
2748                if (getUIClassID().equals(uiClassID)) {
2749                    byte count = JComponent.getWriteObjCounter(this );
2750                    JComponent.setWriteObjCounter(this , --count);
2751                    if (count == 0 && ui != null) {
2752                        ui.installUI(this );
2753                    }
2754                }
2755            }
2756
2757            /**
2758             * Returns a {@code String} representation of this {@code JList}.
2759             * This method is intended to be used only for debugging purposes,
2760             * and the content and format of the returned {@code String} may vary
2761             * between implementations. The returned {@code String} may be empty,
2762             * but may not be {@code null}.
2763             * 
2764             * @return  a {@code String} representation of this {@code JList}.
2765             */
2766            protected String paramString() {
2767                String selectionForegroundString = (selectionForeground != null ? selectionForeground
2768                        .toString()
2769                        : "");
2770                String selectionBackgroundString = (selectionBackground != null ? selectionBackground
2771                        .toString()
2772                        : "");
2773
2774                return super .paramString() + ",fixedCellHeight="
2775                        + fixedCellHeight + ",fixedCellWidth=" + fixedCellWidth
2776                        + ",horizontalScrollIncrement="
2777                        + horizontalScrollIncrement + ",selectionBackground="
2778                        + selectionBackgroundString + ",selectionForeground="
2779                        + selectionForegroundString + ",visibleRowCount="
2780                        + visibleRowCount + ",layoutOrientation="
2781                        + layoutOrientation;
2782            }
2783
2784            /**
2785             * --- Accessibility Support ---
2786             */
2787
2788            /**
2789             * Gets the {@code AccessibleContext} associated with this {@code JList}.
2790             * For {@code JList}, the {@code AccessibleContext} takes the form of an 
2791             * {@code AccessibleJList}.
2792             * <p>
2793             * A new {@code AccessibleJList} instance is created if necessary.
2794             *
2795             * @return an {@code AccessibleJList} that serves as the 
2796             *         {@code AccessibleContext} of this {@code JList}
2797             */
2798            public AccessibleContext getAccessibleContext() {
2799                if (accessibleContext == null) {
2800                    accessibleContext = new AccessibleJList();
2801                }
2802                return accessibleContext;
2803            }
2804
2805            /**
2806             * This class implements accessibility support for the 
2807             * {@code JList} class. It provides an implementation of the 
2808             * Java Accessibility API appropriate to list user-interface 
2809             * elements.
2810             * <p>
2811             * <strong>Warning:</strong>
2812             * Serialized objects of this class will not be compatible with
2813             * future Swing releases. The current serialization support is
2814             * appropriate for short term storage or RMI between applications running
2815             * the same version of Swing.  As of 1.4, support for long term storage
2816             * of all JavaBeans<sup><font size="-2">TM</font></sup>
2817             * has been added to the <code>java.beans</code> package.
2818             * Please see {@link java.beans.XMLEncoder}.
2819             */
2820            protected class AccessibleJList extends AccessibleJComponent
2821                    implements  AccessibleSelection, PropertyChangeListener,
2822                    ListSelectionListener, ListDataListener {
2823
2824                int leadSelectionIndex;
2825
2826                public AccessibleJList() {
2827                    super ();
2828                    JList.this .addPropertyChangeListener(this );
2829                    JList.this .getSelectionModel().addListSelectionListener(
2830                            this );
2831                    JList.this .getModel().addListDataListener(this );
2832                    leadSelectionIndex = JList.this .getLeadSelectionIndex();
2833                }
2834
2835                /**
2836                 * Property Change Listener change method. Used to track changes
2837                 * to the DataModel and ListSelectionModel, in order to re-set
2838                 * listeners to those for reporting changes there via the Accessibility
2839                 * PropertyChange mechanism.
2840                 *
2841                 * @param e PropertyChangeEvent
2842                 */
2843                public void propertyChange(PropertyChangeEvent e) {
2844                    String name = e.getPropertyName();
2845                    Object oldValue = e.getOldValue();
2846                    Object newValue = e.getNewValue();
2847
2848                    // re-set listData listeners
2849                    if (name.compareTo("model") == 0) {
2850
2851                        if (oldValue != null && oldValue instanceof  ListModel) {
2852                            ((ListModel) oldValue).removeListDataListener(this );
2853                        }
2854                        if (newValue != null && newValue instanceof  ListModel) {
2855                            ((ListModel) newValue).addListDataListener(this );
2856                        }
2857
2858                        // re-set listSelectionModel listeners
2859                    } else if (name.compareTo("selectionModel") == 0) {
2860
2861                        if (oldValue != null
2862                                && oldValue instanceof  ListSelectionModel) {
2863                            ((ListSelectionModel) oldValue)
2864                                    .removeListSelectionListener(this );
2865                        }
2866                        if (newValue != null
2867                                && newValue instanceof  ListSelectionModel) {
2868                            ((ListSelectionModel) newValue)
2869                                    .addListSelectionListener(this );
2870                        }
2871
2872                        firePropertyChange(
2873                                AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
2874                                Boolean.valueOf(false), Boolean.valueOf(true));
2875                    }
2876                }
2877
2878                /**
2879                 * List Selection Listener value change method. Used to fire 
2880                 * the property change
2881                 *
2882                 * @param e ListSelectionEvent
2883                 *
2884                 */
2885                public void valueChanged(ListSelectionEvent e) {
2886                    int oldLeadSelectionIndex = leadSelectionIndex;
2887                    leadSelectionIndex = JList.this .getLeadSelectionIndex();
2888                    if (oldLeadSelectionIndex != leadSelectionIndex) {
2889                        Accessible oldLS, newLS;
2890                        oldLS = (oldLeadSelectionIndex >= 0) ? getAccessibleChild(oldLeadSelectionIndex)
2891                                : null;
2892                        newLS = (leadSelectionIndex >= 0) ? getAccessibleChild(leadSelectionIndex)
2893                                : null;
2894                        firePropertyChange(
2895                                AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY,
2896                                oldLS, newLS);
2897                    }
2898
2899                    firePropertyChange(
2900                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
2901                            Boolean.valueOf(false), Boolean.valueOf(true));
2902                    firePropertyChange(
2903                            AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
2904                            Boolean.valueOf(false), Boolean.valueOf(true));
2905
2906                    // Process the State changes for Multiselectable
2907                    AccessibleStateSet s = getAccessibleStateSet();
2908                    ListSelectionModel lsm = JList.this .getSelectionModel();
2909                    if (lsm.getSelectionMode() != ListSelectionModel.SINGLE_SELECTION) {
2910                        if (!s.contains(AccessibleState.MULTISELECTABLE)) {
2911                            s.add(AccessibleState.MULTISELECTABLE);
2912                            firePropertyChange(
2913                                    AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
2914                                    null, AccessibleState.MULTISELECTABLE);
2915                        }
2916                    } else {
2917                        if (s.contains(AccessibleState.MULTISELECTABLE)) {
2918                            s.remove(AccessibleState.MULTISELECTABLE);
2919                            firePropertyChange(
2920                                    AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
2921                                    AccessibleState.MULTISELECTABLE, null);
2922                        }
2923                    }
2924                }
2925
2926                /**
2927                 * List Data Listener interval added method. Used to fire the visible data property change
2928                 *
2929                 * @param e ListDataEvent
2930                 *
2931                 */
2932                public void intervalAdded(ListDataEvent e) {
2933                    firePropertyChange(
2934                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
2935                            Boolean.valueOf(false), Boolean.valueOf(true));
2936                }
2937
2938                /**
2939                 * List Data Listener interval removed method. Used to fire the visible data property change
2940                 *
2941                 * @param e ListDataEvent
2942                 *
2943                 */
2944                public void intervalRemoved(ListDataEvent e) {
2945                    firePropertyChange(
2946                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
2947                            Boolean.valueOf(false), Boolean.valueOf(true));
2948                }
2949
2950                /**
2951                 * List Data Listener contents changed method. Used to fire the visible data property change
2952                 *
2953                 * @param e ListDataEvent
2954                 *
2955                 */
2956                public void contentsChanged(ListDataEvent e) {
2957                    firePropertyChange(
2958                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
2959                            Boolean.valueOf(false), Boolean.valueOf(true));
2960                }
2961
2962                // AccessibleContext methods
2963
2964                /**
2965                 * Get the state set of this object.
2966                 *
2967                 * @return an instance of AccessibleState containing the current state
2968                 * of the object
2969                 * @see AccessibleState
2970                 */
2971                public AccessibleStateSet getAccessibleStateSet() {
2972                    AccessibleStateSet states = super .getAccessibleStateSet();
2973                    if (selectionModel.getSelectionMode() != ListSelectionModel.SINGLE_SELECTION) {
2974                        states.add(AccessibleState.MULTISELECTABLE);
2975                    }
2976                    return states;
2977                }
2978
2979                /**
2980                 * Get the role of this object.
2981                 *
2982                 * @return an instance of AccessibleRole describing the role of the
2983                 * object
2984                 * @see AccessibleRole
2985                 */
2986                public AccessibleRole getAccessibleRole() {
2987                    return AccessibleRole.LIST;
2988                }
2989
2990                /**
2991                 * Returns the <code>Accessible</code> child contained at
2992                 * the local coordinate <code>Point</code>, if one exists.
2993                 * Otherwise returns <code>null</code>.
2994                 *
2995                 * @return the <code>Accessible</code> at the specified 
2996                 *    location, if it exists
2997                 */
2998                public Accessible getAccessibleAt(Point p) {
2999                    int i = locationToIndex(p);
3000                    if (i >= 0) {
3001                        return new AccessibleJListChild(JList.this , i);
3002                    } else {
3003                        return null;
3004                    }
3005                }
3006
3007                /**
3008                 * Returns the number of accessible children in the object.  If all
3009                 * of the children of this object implement Accessible, than this
3010                 * method should return the number of children of this object.
3011                 *
3012                 * @return the number of accessible children in the object.
3013                 */
3014                public int getAccessibleChildrenCount() {
3015                    return getModel().getSize();
3016                }
3017
3018                /**
3019                 * Return the nth Accessible child of the object.
3020                 *
3021                 * @param i zero-based index of child
3022                 * @return the nth Accessible child of the object
3023                 */
3024                public Accessible getAccessibleChild(int i) {
3025                    if (i >= getModel().getSize()) {
3026                        return null;
3027                    } else {
3028                        return new AccessibleJListChild(JList.this , i);
3029                    }
3030                }
3031
3032                /**
3033                 * Get the AccessibleSelection associated with this object.  In the
3034                 * implementation of the Java Accessibility API for this class, 
3035                 * return this object, which is responsible for implementing the
3036                 * AccessibleSelection interface on behalf of itself.
3037                 * 
3038                 * @return this object
3039                 */
3040                public AccessibleSelection getAccessibleSelection() {
3041                    return this ;
3042                }
3043
3044                // AccessibleSelection methods
3045
3046                /**
3047                 * Returns the number of items currently selected.
3048                 * If no items are selected, the return value will be 0.
3049                 *
3050                 * @return the number of items currently selected.
3051                 */
3052                public int getAccessibleSelectionCount() {
3053                    return JList.this .getSelectedIndices().length;
3054                }
3055
3056                /**
3057                 * Returns an Accessible representing the specified selected item
3058                 * in the object.  If there isn't a selection, or there are
3059                 * fewer items selected than the integer passed in, the return
3060                 * value will be <code>null</code>.
3061                 *
3062                 * @param i the zero-based index of selected items
3063                 * @return an Accessible containing the selected item
3064                 */
3065                public Accessible getAccessibleSelection(int i) {
3066                    int len = getAccessibleSelectionCount();
3067                    if (i < 0 || i >= len) {
3068                        return null;
3069                    } else {
3070                        return getAccessibleChild(JList.this 
3071                                .getSelectedIndices()[i]);
3072                    }
3073                }
3074
3075                /**
3076                 * Returns true if the current child of this object is selected.
3077                 *
3078                 * @param i the zero-based index of the child in this Accessible
3079                 * object.
3080                 * @see AccessibleContext#getAccessibleChild
3081                 */
3082                public boolean isAccessibleChildSelected(int i) {
3083                    return isSelectedIndex(i);
3084                }
3085
3086                /**
3087                 * Adds the specified selected item in the object to the object's
3088                 * selection.  If the object supports multiple selections,
3089                 * the specified item is added to any existing selection, otherwise
3090                 * it replaces any existing selection in the object.  If the
3091                 * specified item is already selected, this method has no effect.
3092                 *
3093                 * @param i the zero-based index of selectable items
3094                 */
3095                public void addAccessibleSelection(int i) {
3096                    JList.this .addSelectionInterval(i, i);
3097                }
3098
3099                /**
3100                 * Removes the specified selected item in the object from the object's
3101                 * selection.  If the specified item isn't currently selected, this
3102                 * method has no effect.
3103                 *
3104                 * @param i the zero-based index of selectable items
3105                 */
3106                public void removeAccessibleSelection(int i) {
3107                    JList.this .removeSelectionInterval(i, i);
3108                }
3109
3110                /**
3111                 * Clears the selection in the object, so that nothing in the
3112                 * object is selected.
3113                 */
3114                public void clearAccessibleSelection() {
3115                    JList.this .clearSelection();
3116                }
3117
3118                /**
3119                 * Causes every selected item in the object to be selected
3120                 * if the object supports multiple selections.
3121                 */
3122                public void selectAllAccessibleSelection() {
3123                    JList.this .addSelectionInterval(0,
3124                            getAccessibleChildrenCount() - 1);
3125                }
3126
3127                /**
3128                 * This class implements accessibility support appropriate 
3129                 * for list children.
3130                 */
3131                protected class AccessibleJListChild extends AccessibleContext
3132                        implements  Accessible, AccessibleComponent {
3133                    private JList parent = null;
3134                    private int indexInParent;
3135                    private Component component = null;
3136                    private AccessibleContext accessibleContext = null;
3137                    private ListModel listModel;
3138                    private ListCellRenderer cellRenderer = null;
3139
3140                    public AccessibleJListChild(JList parent, int indexInParent) {
3141                        this .parent = parent;
3142                        this .setAccessibleParent(parent);
3143                        this .indexInParent = indexInParent;
3144                        if (parent != null) {
3145                            listModel = parent.getModel();
3146                            cellRenderer = parent.getCellRenderer();
3147                        }
3148                    }
3149
3150                    private Component getCurrentComponent() {
3151                        return getComponentAtIndex(indexInParent);
3152                    }
3153
3154                    private AccessibleContext getCurrentAccessibleContext() {
3155                        Component c = getComponentAtIndex(indexInParent);
3156                        if (c instanceof  Accessible) {
3157                            return ((Accessible) c).getAccessibleContext();
3158                        } else {
3159                            return null;
3160                        }
3161                    }
3162
3163                    private Component getComponentAtIndex(int index) {
3164                        if (index < 0 || index >= listModel.getSize()) {
3165                            return null;
3166                        }
3167                        if ((parent != null) && (listModel != null)
3168                                && cellRenderer != null) {
3169                            Object value = listModel.getElementAt(index);
3170                            boolean isSelected = parent.isSelectedIndex(index);
3171                            boolean isFocussed = parent.isFocusOwner()
3172                                    && (index == parent.getLeadSelectionIndex());
3173                            return cellRenderer.getListCellRendererComponent(
3174                                    parent, value, index, isSelected,
3175                                    isFocussed);
3176                        } else {
3177                            return null;
3178                        }
3179                    }
3180
3181                    // Accessible Methods
3182                    /**
3183                     * Get the AccessibleContext for this object. In the 
3184                     * implementation of the Java Accessibility API for this class, 
3185                     * returns this object, which is its own AccessibleContext.
3186                     * 
3187                     * @return this object
3188                     */
3189                    public AccessibleContext getAccessibleContext() {
3190                        return this ;
3191                    }
3192
3193                    // AccessibleContext methods
3194
3195                    public String getAccessibleName() {
3196                        AccessibleContext ac = getCurrentAccessibleContext();
3197                        if (ac != null) {
3198                            return ac.getAccessibleName();
3199                        } else {
3200                            return null;
3201                        }
3202                    }
3203
3204                    public void setAccessibleName(String s) {
3205                        AccessibleContext ac = getCurrentAccessibleContext();
3206                        if (ac != null) {
3207                            ac.setAccessibleName(s);
3208                        }
3209                    }
3210
3211                    public String getAccessibleDescription() {
3212                        AccessibleContext ac = getCurrentAccessibleContext();
3213                        if (ac != null) {
3214                            return ac.getAccessibleDescription();
3215                        } else {
3216                            return null;
3217                        }
3218                    }
3219
3220                    public void setAccessibleDescription(String s) {
3221                        AccessibleContext ac = getCurrentAccessibleContext();
3222                        if (ac != null) {
3223                            ac.setAccessibleDescription(s);
3224                        }
3225                    }
3226
3227                    public AccessibleRole getAccessibleRole() {
3228                        AccessibleContext ac = getCurrentAccessibleContext();
3229                        if (ac != null) {
3230                            return ac.getAccessibleRole();
3231                        } else {
3232                            return null;
3233                        }
3234                    }
3235
3236                    public AccessibleStateSet getAccessibleStateSet() {
3237                        AccessibleContext ac = getCurrentAccessibleContext();
3238                        AccessibleStateSet s;
3239                        if (ac != null) {
3240                            s = ac.getAccessibleStateSet();
3241                        } else {
3242                            s = new AccessibleStateSet();
3243                        }
3244
3245                        s.add(AccessibleState.SELECTABLE);
3246                        if (parent.isFocusOwner()
3247                                && (indexInParent == parent
3248                                        .getLeadSelectionIndex())) {
3249                            s.add(AccessibleState.ACTIVE);
3250                        }
3251                        if (parent.isSelectedIndex(indexInParent)) {
3252                            s.add(AccessibleState.SELECTED);
3253                        }
3254                        if (this .isShowing()) {
3255                            s.add(AccessibleState.SHOWING);
3256                        } else if (s.contains(AccessibleState.SHOWING)) {
3257                            s.remove(AccessibleState.SHOWING);
3258                        }
3259                        if (this .isVisible()) {
3260                            s.add(AccessibleState.VISIBLE);
3261                        } else if (s.contains(AccessibleState.VISIBLE)) {
3262                            s.remove(AccessibleState.VISIBLE);
3263                        }
3264                        s.add(AccessibleState.TRANSIENT); // cell-rendered
3265                        return s;
3266                    }
3267
3268                    public int getAccessibleIndexInParent() {
3269                        return indexInParent;
3270                    }
3271
3272                    public int getAccessibleChildrenCount() {
3273                        AccessibleContext ac = getCurrentAccessibleContext();
3274                        if (ac != null) {
3275                            return ac.getAccessibleChildrenCount();
3276                        } else {
3277                            return 0;
3278                        }
3279                    }
3280
3281                    public Accessible getAccessibleChild(int i) {
3282                        AccessibleContext ac = getCurrentAccessibleContext();
3283                        if (ac != null) {
3284                            Accessible accessibleChild = ac
3285                                    .getAccessibleChild(i);
3286                            ac.setAccessibleParent(this );
3287                            return accessibleChild;
3288                        } else {
3289                            return null;
3290                        }
3291                    }
3292
3293                    public Locale getLocale() {
3294                        AccessibleContext ac = getCurrentAccessibleContext();
3295                        if (ac != null) {
3296                            return ac.getLocale();
3297                        } else {
3298                            return null;
3299                        }
3300                    }
3301
3302                    public void addPropertyChangeListener(
3303                            PropertyChangeListener l) {
3304                        AccessibleContext ac = getCurrentAccessibleContext();
3305                        if (ac != null) {
3306                            ac.addPropertyChangeListener(l);
3307                        }
3308                    }
3309
3310                    public void removePropertyChangeListener(
3311                            PropertyChangeListener l) {
3312                        AccessibleContext ac = getCurrentAccessibleContext();
3313                        if (ac != null) {
3314                            ac.removePropertyChangeListener(l);
3315                        }
3316                    }
3317
3318                    public AccessibleAction getAccessibleAction() {
3319                        return getCurrentAccessibleContext()
3320                                .getAccessibleAction();
3321                    }
3322
3323                    /**
3324                     * Get the AccessibleComponent associated with this object.  In the
3325                     * implementation of the Java Accessibility API for this class, 
3326                     * return this object, which is responsible for implementing the
3327                     * AccessibleComponent interface on behalf of itself.
3328                     * 
3329                     * @return this object
3330                     */
3331                    public AccessibleComponent getAccessibleComponent() {
3332                        return this ; // to override getBounds()
3333                    }
3334
3335                    public AccessibleSelection getAccessibleSelection() {
3336                        return getCurrentAccessibleContext()
3337                                .getAccessibleSelection();
3338                    }
3339
3340                    public AccessibleText getAccessibleText() {
3341                        return getCurrentAccessibleContext()
3342                                .getAccessibleText();
3343                    }
3344
3345                    public AccessibleValue getAccessibleValue() {
3346                        return getCurrentAccessibleContext()
3347                                .getAccessibleValue();
3348                    }
3349
3350                    // AccessibleComponent methods
3351
3352                    public Color getBackground() {
3353                        AccessibleContext ac = getCurrentAccessibleContext();
3354                        if (ac instanceof  AccessibleComponent) {
3355                            return ((AccessibleComponent) ac).getBackground();
3356                        } else {
3357                            Component c = getCurrentComponent();
3358                            if (c != null) {
3359                                return c.getBackground();
3360                            } else {
3361                                return null;
3362                            }
3363                        }
3364                    }
3365
3366                    public void setBackground(Color c) {
3367                        AccessibleContext ac = getCurrentAccessibleContext();
3368                        if (ac instanceof  AccessibleComponent) {
3369                            ((AccessibleComponent) ac).setBackground(c);
3370                        } else {
3371                            Component cp = getCurrentComponent();
3372                            if (cp != null) {
3373                                cp.setBackground(c);
3374                            }
3375                        }
3376                    }
3377
3378                    public Color getForeground() {
3379                        AccessibleContext ac = getCurrentAccessibleContext();
3380                        if (ac instanceof  AccessibleComponent) {
3381                            return ((AccessibleComponent) ac).getForeground();
3382                        } else {
3383                            Component c = getCurrentComponent();
3384                            if (c != null) {
3385                                return c.getForeground();
3386                            } else {
3387                                return null;
3388                            }
3389                        }
3390                    }
3391
3392                    public void setForeground(Color c) {
3393                        AccessibleContext ac = getCurrentAccessibleContext();
3394                        if (ac instanceof  AccessibleComponent) {
3395                            ((AccessibleComponent) ac).setForeground(c);
3396                        } else {
3397                            Component cp = getCurrentComponent();
3398                            if (cp != null) {
3399                                cp.setForeground(c);
3400                            }
3401                        }
3402                    }
3403
3404                    public Cursor getCursor() {
3405                        AccessibleContext ac = getCurrentAccessibleContext();
3406                        if (ac instanceof  AccessibleComponent) {
3407                            return ((AccessibleComponent) ac).getCursor();
3408                        } else {
3409                            Component c = getCurrentComponent();
3410                            if (c != null) {
3411                                return c.getCursor();
3412                            } else {
3413                                Accessible ap = getAccessibleParent();
3414                                if (ap instanceof  AccessibleComponent) {
3415                                    return ((AccessibleComponent) ap)
3416                                            .getCursor();
3417                                } else {
3418                                    return null;
3419                                }
3420                            }
3421                        }
3422                    }
3423
3424                    public void setCursor(Cursor c) {
3425                        AccessibleContext ac = getCurrentAccessibleContext();
3426                        if (ac instanceof  AccessibleComponent) {
3427                            ((AccessibleComponent) ac).setCursor(c);
3428                        } else {
3429                            Component cp = getCurrentComponent();
3430                            if (cp != null) {
3431                                cp.setCursor(c);
3432                            }
3433                        }
3434                    }
3435
3436                    public Font getFont() {
3437                        AccessibleContext ac = getCurrentAccessibleContext();
3438                        if (ac instanceof  AccessibleComponent) {
3439                            return ((AccessibleComponent) ac).getFont();
3440                        } else {
3441                            Component c = getCurrentComponent();
3442                            if (c != null) {
3443                                return c.getFont();
3444                            } else {
3445                                return null;
3446                            }
3447                        }
3448                    }
3449
3450                    public void setFont(Font f) {
3451                        AccessibleContext ac = getCurrentAccessibleContext();
3452                        if (ac instanceof  AccessibleComponent) {
3453                            ((AccessibleComponent) ac).setFont(f);
3454                        } else {
3455                            Component c = getCurrentComponent();
3456                            if (c != null) {
3457                                c.setFont(f);
3458                            }
3459                        }
3460                    }
3461
3462                    public FontMetrics getFontMetrics(Font f) {
3463                        AccessibleContext ac = getCurrentAccessibleContext();
3464                        if (ac instanceof  AccessibleComponent) {
3465                            return ((AccessibleComponent) ac).getFontMetrics(f);
3466                        } else {
3467                            Component c = getCurrentComponent();
3468                            if (c != null) {
3469                                return c.getFontMetrics(f);
3470                            } else {
3471                                return null;
3472                            }
3473                        }
3474                    }
3475
3476                    public boolean isEnabled() {
3477                        AccessibleContext ac = getCurrentAccessibleContext();
3478                        if (ac instanceof  AccessibleComponent) {
3479                            return ((AccessibleComponent) ac).isEnabled();
3480                        } else {
3481                            Component c = getCurrentComponent();
3482                            if (c != null) {
3483                                return c.isEnabled();
3484                            } else {
3485                                return false;
3486                            }
3487                        }
3488                    }
3489
3490                    public void setEnabled(boolean b) {
3491                        AccessibleContext ac = getCurrentAccessibleContext();
3492                        if (ac instanceof  AccessibleComponent) {
3493                            ((AccessibleComponent) ac).setEnabled(b);
3494                        } else {
3495                            Component c = getCurrentComponent();
3496                            if (c != null) {
3497                                c.setEnabled(b);
3498                            }
3499                        }
3500                    }
3501
3502                    public boolean isVisible() {
3503                        int fi = parent.getFirstVisibleIndex();
3504                        int li = parent.getLastVisibleIndex();
3505                        // The UI incorrectly returns a -1 for the last
3506                        // visible index if the list is smaller than the
3507                        // viewport size.
3508                        if (li == -1) {
3509                            li = parent.getModel().getSize() - 1;
3510                        }
3511                        return ((indexInParent >= fi) && (indexInParent <= li));
3512                    }
3513
3514                    public void setVisible(boolean b) {
3515                    }
3516
3517                    public boolean isShowing() {
3518                        return (parent.isShowing() && isVisible());
3519                    }
3520
3521                    public boolean contains(Point p) {
3522                        AccessibleContext ac = getCurrentAccessibleContext();
3523                        if (ac instanceof  AccessibleComponent) {
3524                            Rectangle r = ((AccessibleComponent) ac)
3525                                    .getBounds();
3526                            return r.contains(p);
3527                        } else {
3528                            Component c = getCurrentComponent();
3529                            if (c != null) {
3530                                Rectangle r = c.getBounds();
3531                                return r.contains(p);
3532                            } else {
3533                                return getBounds().contains(p);
3534                            }
3535                        }
3536                    }
3537
3538                    public Point getLocationOnScreen() {
3539                        if (parent != null) {
3540                            Point listLocation = parent.getLocationOnScreen();
3541                            Point componentLocation = parent
3542                                    .indexToLocation(indexInParent);
3543                            if (componentLocation != null) {
3544                                componentLocation.translate(listLocation.x,
3545                                        listLocation.y);
3546                                return componentLocation;
3547                            } else {
3548                                return null;
3549                            }
3550                        } else {
3551                            return null;
3552                        }
3553                    }
3554
3555                    public Point getLocation() {
3556                        if (parent != null) {
3557                            return parent.indexToLocation(indexInParent);
3558                        } else {
3559                            return null;
3560                        }
3561                    }
3562
3563                    public void setLocation(Point p) {
3564                        if ((parent != null) && (parent.contains(p))) {
3565                            ensureIndexIsVisible(indexInParent);
3566                        }
3567                    }
3568
3569                    public Rectangle getBounds() {
3570                        if (parent != null) {
3571                            return parent.getCellBounds(indexInParent,
3572                                    indexInParent);
3573                        } else {
3574                            return null;
3575                        }
3576                    }
3577
3578                    public void setBounds(Rectangle r) {
3579                        AccessibleContext ac = getCurrentAccessibleContext();
3580                        if (ac instanceof  AccessibleComponent) {
3581                            ((AccessibleComponent) ac).setBounds(r);
3582                        }
3583                    }
3584
3585                    public Dimension getSize() {
3586                        Rectangle cellBounds = this .getBounds();
3587                        if (cellBounds != null) {
3588                            return cellBounds.getSize();
3589                        } else {
3590                            return null;
3591                        }
3592                    }
3593
3594                    public void setSize(Dimension d) {
3595                        AccessibleContext ac = getCurrentAccessibleContext();
3596                        if (ac instanceof  AccessibleComponent) {
3597                            ((AccessibleComponent) ac).setSize(d);
3598                        } else {
3599                            Component c = getCurrentComponent();
3600                            if (c != null) {
3601                                c.setSize(d);
3602                            }
3603                        }
3604                    }
3605
3606                    public Accessible getAccessibleAt(Point p) {
3607                        AccessibleContext ac = getCurrentAccessibleContext();
3608                        if (ac instanceof  AccessibleComponent) {
3609                            return ((AccessibleComponent) ac)
3610                                    .getAccessibleAt(p);
3611                        } else {
3612                            return null;
3613                        }
3614                    }
3615
3616                    public boolean isFocusTraversable() {
3617                        AccessibleContext ac = getCurrentAccessibleContext();
3618                        if (ac instanceof  AccessibleComponent) {
3619                            return ((AccessibleComponent) ac)
3620                                    .isFocusTraversable();
3621                        } else {
3622                            Component c = getCurrentComponent();
3623                            if (c != null) {
3624                                return c.isFocusTraversable();
3625                            } else {
3626                                return false;
3627                            }
3628                        }
3629                    }
3630
3631                    public void requestFocus() {
3632                        AccessibleContext ac = getCurrentAccessibleContext();
3633                        if (ac instanceof  AccessibleComponent) {
3634                            ((AccessibleComponent) ac).requestFocus();
3635                        } else {
3636                            Component c = getCurrentComponent();
3637                            if (c != null) {
3638                                c.requestFocus();
3639                            }
3640                        }
3641                    }
3642
3643                    public void addFocusListener(FocusListener l) {
3644                        AccessibleContext ac = getCurrentAccessibleContext();
3645                        if (ac instanceof  AccessibleComponent) {
3646                            ((AccessibleComponent) ac).addFocusListener(l);
3647                        } else {
3648                            Component c = getCurrentComponent();
3649                            if (c != null) {
3650                                c.addFocusListener(l);
3651                            }
3652                        }
3653                    }
3654
3655                    public void removeFocusListener(FocusListener l) {
3656                        AccessibleContext ac = getCurrentAccessibleContext();
3657                        if (ac instanceof  AccessibleComponent) {
3658                            ((AccessibleComponent) ac).removeFocusListener(l);
3659                        } else {
3660                            Component c = getCurrentComponent();
3661                            if (c != null) {
3662                                c.removeFocusListener(l);
3663                            }
3664                        }
3665                    }
3666
3667                    // TIGER - 4733624
3668                    /**
3669                     * Returns the icon for the element renderer, as the only item
3670                     * of an array of <code>AccessibleIcon</code>s or a <code>null</code> array
3671                     * if the renderer component contains no icons.
3672                     *
3673                     * @return an array containing the accessible icon
3674                     *         or a <code>null</code> array if none
3675                     * @since 1.3
3676                     */
3677                    public AccessibleIcon[] getAccessibleIcon() {
3678                        AccessibleContext ac = getCurrentAccessibleContext();
3679                        if (ac != null) {
3680                            return ac.getAccessibleIcon();
3681                        } else {
3682                            return null;
3683                        }
3684                    }
3685                } // inner class AccessibleJListChild
3686            } // inner class AccessibleJList
3687        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.