home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / jfc.bin / JList.java < prev    next >
Text File  |  1998-02-26  |  78KB  |  2,242 lines

  1. /*
  2.  * @(#)JList.java    1.37 98/02/12
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20.  
  21. package com.sun.java.swing;
  22.  
  23. import java.awt.event.*;
  24. import java.awt.Color;
  25. import java.awt.Component;
  26. import java.awt.Cursor;
  27. import java.awt.Font;
  28. import java.awt.FontMetrics;
  29. import java.awt.Point;
  30. import java.awt.Rectangle;
  31. import java.awt.Insets;
  32. import java.awt.Dimension;
  33. import java.util.Vector;
  34. import java.util.Locale;
  35. import java.beans.PropertyChangeListener;
  36. import com.sun.java.swing.event.*;
  37. import com.sun.java.accessibility.*;
  38. import com.sun.java.swing.plaf.*;
  39.  
  40.  
  41. /**
  42.    A component that allows the user to select one or more objects from a
  43.    list.  A separate model, <code>ListModel</code>, represents the contents
  44.    of the list.  It's easy to display an array or vector of objects, using
  45.    a JList constructor that builds an ListModel instance for you:
  46.    <pre>
  47.    // Create a JList that displays the strings in data[]
  48.  
  49.    String[] data = {"one", "two", "free", "four"};
  50.    JList dataList = new JList(data);
  51.  
  52.    // The value JList model property is an object that provides
  53.    // a read-only view of the data.  It was constructed automatically.
  54.  
  55.    for(int i = 0; i < dataList.getModel().getSize(); i++) {
  56.        System.out.println(dataList.getModel().getElementAt(i));
  57.    }
  58.  
  59.    // Create a JList that displays the superclass of JList.class.
  60.    //   We store the superclasses in a java.util.Vector.
  61.  
  62.    Vector superClasses = new Vector();
  63.    Class rootClass = com.sun.java.swing.JList.class;
  64.    for(Class cls = rootClass; cls != null; cls = cls.getSuperclass()) {
  65.        superClasses.addElement(cls);
  66.    }
  67.    JList classList = new JList(superClasses);
  68.    </pre>
  69.    <p>
  70.    JList doesn't support scrolling directly.  To create a scrolling
  71.    list you make the JList the viewport view of a JScrollPane, e.g.
  72.    <pre>
  73.    JScrollPane scrollPane = new JScrollPane(dataList);
  74.    // Or in two steps:
  75.    JScrollPane scrollPane = new JScrollPane();
  76.    scrollPane.getViewport().setView(dataList);
  77.    </pre>
  78.    <p>
  79.    By default JList supports single selection, i.e. zero or one
  80.    index can be selected.  The selection state is actually managed
  81.    by a separate delegate object, an implementation of <code>ListSelectionModel</code>
  82.    however JList provides convenient properties for managing the selection.
  83.    <pre>
  84.    String[] data = {"one", "two", "free", "four"};
  85.    JList dataList = new JList(data);
  86.  
  87.    dataList.setSelectedIndex(1);  // select "two"
  88.    dataList.getSelectedValue();   // returns "two"
  89.    </pre>
  90.    <p>
  91.    The contents of a JList can be dynamic, i.e. the list elements can
  92.    change value and the size of the list can change after the JList has
  93.    been created.  The JList observes changes in its model with a
  94.    <code>ListModelListener</code>.  A correct implementation of ListModel
  95.    will notify it's listeners each time a change occurs.  The changes are
  96.    characterized by a <code>ListModelEvent</code> that simply identifies
  97.    the range of List indices that have been modified, added, or removed.
  98.    Simple dynamic content JList applications can use the
  99.    <code>DefaultListModel</code> class to store list elements.  This class
  100.    implements the ListModel interfaces and provides all of the
  101.    java.util.Vector API as well.  Applications that need to provide
  102.    custom ListModel implementations may want to subclass AbstractListModel,
  103.    which provides basic ListModelListener support.  For example:
  104.    <pre>
  105.    // This list model has about 2^16 elements.  Enjoy scrolling.
  106.  
  107.    ListModel bigData = new AbstractListModel() {
  108.        public int getSize() { return Short.MAX_VALUE; }
  109.        public Object getElementAt(int index) { return "Index " + index; }
  110.    };
  111.  
  112.    JList bigDataList = new List(bigData);
  113.  
  114.    // We don't want the JList implementation to compute the width
  115.    // or height of all of the list cells, so we give it a String
  116.    // that's as big as we'll need for any cell.  It uses this to
  117.    // compute values for the fixedCellWidth and fixedCellHeight
  118.    // properties.
  119.  
  120.    bigDataList.setPrototypeCellValue("Index 1234567890");
  121.    </pre>
  122.    <p>
  123.    JList uses a java.awt.Component, provided by a delegate called the
  124.    <code>cellRendererer</code>, to paint the visible cells in the list.
  125.    The cellRenderer component is used like a "rubber stamp" to paint
  126.    each visible row.  Each time the JList needs to paint a cell
  127.    it asks the cellRenderer for the component, moves it into place
  128.    with setBounds() and then draws it by calling its paint method.
  129.    The default cellRenderer uses a JLabel component to render
  130.    the string value of each component.   You can substitute your
  131.    own cellRenderer, e.g.:
  132.    <pre>
  133.     // Display an icon and a string for each object in the list.
  134.  
  135.    class MyCellRenderer extends JLabel implements ListCellRenderer {
  136.        final static ImageIcon longIcon = new ImageIcon("long.gif");
  137.        final static ImageIcon shortIcon = new ImageIcon("short.gif");
  138.  
  139.        // This is the only method defined by ListCellRenderer.  We just
  140.        // reconfigure the Jlabel each time we're called.
  141.  
  142.        public Component getListCellRendererComponent(
  143.          JList list,
  144.          Object value,            // value to display
  145.          int index,               // cell index
  146.          boolean isSelected,      // is the cell selected
  147.          boolean cellHasFocus)    // the list and the cell have the focus
  148.        {
  149.           String s = value.toString();
  150.            setText(s);
  151.            setIcon((s.length > 10) ? longIcon : shortIcon);
  152.         return this;
  153.        }
  154.    }
  155.  
  156.    String[] data = {"one", "two", "free", "four"};
  157.    JList dataList = new JList(data);
  158.    dataList.setCellRenderer(new MyCellRenderer());
  159.    </pre>
  160.    <p>
  161.    JList doesn't provide any special support for handling double or
  162.    triple (or N) mouse clicks however it's easy to handle them using
  163.    a MouseListener.  Just use the JList locationToIndex() method to
  164.    determine what cell was clicked on.  For example:
  165.    <pre>
  166.    final JList list = new JList(dataModel);
  167.    MouseListener mouseListener = new MouseAdapter() {
  168.        public void mouseClicked(MouseEvent e) {
  169.            if (e.getClickCount() == 2) {
  170.                int index = list.locationToIndex(e.getPoint());
  171.                System.out.println("Double clicked on Item " + index);
  172.             }
  173.        }
  174.    };
  175.    list.addMouseListener(mouseListener);
  176.    </pre>
  177.  * Note that in this example the JList variable is <code>final</code>
  178.  * because it's referred to by the anonymous MouseListener class.
  179.  * <p>
  180.  * Warning: serialized objects of this class will not be compatible with
  181.  * future swing releases.  The current serialization support is appropriate
  182.  * for short term storage or RMI between Swing1.0 applications.  It will
  183.  * not be possible to load serialized Swing1.0 objects with future releases
  184.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  185.  * baseline for the serialized form of Swing objects.
  186.  *
  187.  * @see ListModel
  188.  * @see AbstractListModel
  189.  * @see DefaultListModel
  190.  * @see ListSelectionModel
  191.  * @see DefaultListSelectionModel
  192.  * @see ListCellRenderer
  193.  *
  194.  * @beaninfo
  195.  *   attribute: isContainer false
  196.  *
  197.  * @version 1.37 02/12/98
  198.  * @author Hans Muller
  199.  */
  200. public class JList extends JComponent implements Scrollable, Accessible
  201. {
  202.     private int fixedCellWidth = -1;
  203.     private int fixedCellHeight = -1;
  204.     private Object prototypeCellValue;
  205.     private int visibleRowCount = 8;
  206.     private Color selectionForeground;
  207.     private Color selectionBackground;
  208.  
  209.     private ListSelectionModel selectionModel;
  210.     private ListModel dataModel;
  211.     private ListCellRenderer cellRenderer;
  212.     private ListSelectionListener selectionListener;
  213.  
  214.  
  215.     /**
  216.      * Construct a JList that displays the elements in the specified,
  217.      * non-null model.  All JList constructors delegate to this one.
  218.      */
  219.     public JList(ListModel dataModel)
  220.     {
  221.         if (dataModel == null) {
  222.             throw new IllegalArgumentException("dataModel must be non null");
  223.         }
  224.  
  225.         this.dataModel = dataModel;
  226.         selectionModel = createSelectionModel();
  227.         setAutoscrolls(true);
  228.         updateUI();
  229.     }
  230.  
  231.  
  232.     /**
  233.      * Construct a JList that displays the elements in the specified
  234.      * array.  This constructor just delegates to the ListModel
  235.      * constructor.
  236.      */
  237.     public JList(final Object[] listData)
  238.     {
  239.         this (
  240.             new AbstractListModel() {
  241.                 public int getSize() { return listData.length; }
  242.                 public Object getElementAt(int i) { return listData[i]; }
  243.             }
  244.         );
  245.     }
  246.  
  247.  
  248.     /**
  249.      * Construct a JList that displays the elements in the specified
  250.      * Vector.  This constructor just delegates to the ListModel
  251.      * constructor.
  252.      */
  253.     public JList(final Vector listData) {
  254.         this (
  255.             new AbstractListModel() {
  256.                 public int getSize() { return listData.size(); }
  257.                 public Object getElementAt(int i) { return listData.elementAt(i); }
  258.             }
  259.         );
  260.     }
  261.  
  262.  
  263.     /**
  264.      * Constructs a JList with an empty model.
  265.      */
  266.     public JList() {
  267.         this (
  268.             new AbstractListModel() {
  269.               public int getSize() { return 0; }
  270.               public Object getElementAt(int i) { return "No Data Model"; }
  271.             }
  272.         );
  273.     }
  274.  
  275.  
  276.     /**
  277.      * Returns the L&F object that renders this component.
  278.      *
  279.      * @return the ListUI object that renders this component
  280.      */
  281.     public ListUI getUI() {
  282.         return (ListUI)ui;
  283.     }
  284.  
  285.  
  286.     /**
  287.      * Sets the L&F object that renders this component.
  288.      *
  289.      * @param ui  the ListUI L&F object
  290.      * @see UIDefaults#getUI
  291.      */
  292.     public void setUI(ListUI ui) {
  293.         super.setUI(ui);
  294.     }
  295.  
  296.  
  297.     /**
  298.      * Set the UI property with the "ListUI" from the current default
  299.      * UIFactory.  This method is called by the JList constructor and
  300.      * to update the Lists look and feel at runtime.
  301.      *
  302.      * @see UIManager#getUI
  303.      */
  304.     public void updateUI() {
  305.         setUI((ListUI)UIManager.getUI(this));
  306.         invalidate();
  307.     }
  308.  
  309.  
  310.     /**
  311.      * Returns the name of the UIFactory class that generates the
  312.      * look and feel for this component.
  313.      *
  314.      * @return "ListUI"
  315.      * @see JComponent#getUIClassID
  316.      * @see UIDefaults#getUI
  317.      */
  318.     public String getUIClassID() {
  319.         return "ListUI";
  320.     }
  321.  
  322.  
  323.     /**
  324.      * JList components are opaque. They paint every pixel in their
  325.      * area, so that none of the pixels underneath show through.
  326.      *
  327.      * @return true
  328.      */
  329.     public boolean isOpaque() {
  330.         return true;
  331.     }
  332.  
  333.  
  334.     /* -----private-----
  335.      * This method is called by setPrototypeCellValue and setCellRenderer
  336.      * to update the fixedCellWidth and fixedCellHeight properties from the
  337.      * current value of prototypeCellValue (if it's non null).
  338.      * <p>
  339.      * This method sets fixedCellWidth and fixedCellHeight but does <b>not</b>
  340.      * generate PropertyChangeEvents for them.
  341.      *
  342.      * @see #setPrototypeCellValue
  343.      * @see #setCellRenderer
  344.      */
  345.     private void updateFixedCellSize()
  346.     {
  347.         ListCellRenderer cr = getCellRenderer();
  348.         Object value = getPrototypeCellValue();
  349.  
  350.         if ((cr != null) && (value != null)) {
  351.             Component c = cr.getListCellRendererComponent(this, value, 0, false, false);
  352.  
  353.             /* The ListUI implementation will add Component c to its private
  354.              * CellRendererPane however we can't assume that's already
  355.              * been done here.  So we temporarilty set the one "inherited"
  356.              * property that may affect the renderer components preferred size:
  357.              * its font.
  358.              */
  359.             Font f = c.getFont();
  360.             c.setFont(getFont());
  361.  
  362.             Dimension d = c.getPreferredSize();
  363.             fixedCellWidth = d.width;
  364.             fixedCellHeight = d.height;
  365.  
  366.             c.setFont(f);
  367.         }
  368.     }
  369.  
  370.  
  371.     /**
  372.      * Returns the cell width of the "prototypical cell" -- a cell used
  373.      * for the calculation of cell widths, because it has the same value
  374.      * as all other list items, instead of forcing the calculation to
  375.      * inspect every item in the list.
  376.      *
  377.      * @return the value of the prototypeCellValue property
  378.      * @see #setPrototypeCellValue
  379.      */
  380.     public Object getPrototypeCellValue() {
  381.         return prototypeCellValue;
  382.     }
  383.  
  384.     /**
  385.      * If this value is non-null it's used to compute fixedCellWidth
  386.      * and fixedCellHeight by configuring the cellRenderer at index equals
  387.      * zero for the specified value and then computing the renderer components
  388.      * preferred size.  This property is useful when the list is too long
  389.      * to allow JList to just compute the width/height of each cell
  390.      * and there's single cell value that's known to occupy as much space
  391.      * as any of the others.
  392.      * <p>
  393.      * The default value of this property is null.
  394.      * <p>
  395.      * This is a JavaBeans bound property.  Note that we do set
  396.      * the fixedCellWidth and fixedCellHeight properties here but
  397.      * only a prototypeCellValue PropertyChangeEvent is fired.
  398.      *
  399.      * @param the value to base fixedCellWidth and fixedCellHeight on
  400.      * @see #getPrototypeCellValue
  401.      * @see #setFixedCellWidth
  402.      * @see #setFixedCellHeight
  403.      * @see JComponent#addPropertyChangeListener
  404.      * @beaninfo
  405.      *       bound: true
  406.      * description: The cell prototype value, used to compute cell width and height.
  407.      */
  408.     public void setPrototypeCellValue(Object prototypeCellValue) {
  409.         Object oldValue = this.prototypeCellValue;
  410.         this.prototypeCellValue = prototypeCellValue;
  411.  
  412.         /* If the cellRenderer has changed and prototypeCellValue
  413.          * was set, then recompute fixedCellWidth and fixedCellHeight.
  414.          */
  415.  
  416.         if ((prototypeCellValue != null) && !prototypeCellValue.equals(oldValue)) {
  417.             updateFixedCellSize();
  418.         }
  419.  
  420.         firePropertyChange("prototypeCellValue", oldValue, prototypeCellValue);
  421.     }
  422.  
  423.  
  424.     /**
  425.      * Returns the fixed cell width value -- the value specified by setting
  426.      * the fixedCellWidth property, rather than calculated from the list
  427.      * elements.
  428.      *
  429.      * @return the fixed cell width.
  430.      * @see setFixedCellWidth
  431.      */
  432.     public int getFixedCellWidth() {
  433.         return fixedCellWidth;
  434.     }
  435.  
  436.     /**
  437.      * If this value is greater than zero it defines the width of
  438.      * every cell in the list.  Otherwise cell widths are computed
  439.      * by applying getPreferredSize() to the cellRenderer component
  440.      * for each list element.
  441.      * <p>
  442.      * The default value of this property is -1.
  443.      * <p>
  444.      * This is a JavaBeans bound property.
  445.      *
  446.      * @param the width for all cells in this list
  447.      * @see #getPrototypeCellValue
  448.      * @see #setFixedCellWidth
  449.      * @see JComponent#addPropertyChangeListener
  450.      * @beaninfo
  451.      *       bound: true
  452.      * description: Defines a fixed cell width when greater than zero.
  453.      */
  454.     public void setFixedCellWidth(int width) {
  455.         int oldValue = fixedCellWidth;
  456.         fixedCellWidth = width;
  457.         firePropertyChange("fixedCellWidth", oldValue, fixedCellWidth);
  458.     }
  459.  
  460.  
  461.     /**
  462.      * Returns the fixed cell width value -- the value specified by setting
  463.      * the fixedCellHeight property, rather than calculated from the list
  464.      * elements.
  465.      *
  466.      * @return the fixed cell height.
  467.      * @see setFixedCellHeight
  468.      */
  469.     public int getFixedCellHeight() {
  470.         return fixedCellHeight;
  471.     }
  472.  
  473.     /**
  474.      * If this value is greater than zero it defines the width of
  475.      * every cell in the list.  Otherwise cell widths are computed
  476.      * by applying getPreferredSize() to the cellRenderer component
  477.      * for each list element.
  478.      * <p>
  479.      * The default value of this property is -1.
  480.      * <p>
  481.      * This is a JavaBeans bound property.
  482.      *
  483.      * @param the width for all cells in this list
  484.      * @see #getPrototypeCellValue
  485.      * @see #setFixedCellWidth
  486.      * @see JComponent#addPropertyChangeListener
  487.      * @beaninfo
  488.      *       bound: true
  489.      * description: Defines a fixed cell height when greater than zero.
  490.      */
  491.     public void setFixedCellHeight(int height) {
  492.         int oldValue = fixedCellHeight;
  493.         fixedCellHeight = height;
  494.         firePropertyChange("fixedCellHeight", oldValue, fixedCellHeight);
  495.     }
  496.  
  497.  
  498.     /**
  499.      * Returns the object that renders the list items.
  500.      *
  501.      * @return the ListCellRenderer
  502.      * @see #setCellRenderer
  503.      */
  504.     public ListCellRenderer getCellRenderer() {
  505.         return cellRenderer;
  506.     }
  507.  
  508.     /**
  509.      * Sets the delegate that's used to paint each cell in the list.  If
  510.      * prototypeCellValue was set then the fixedCellWidth and fixedCellHeight
  511.      * properties are set as well.  Only one PropertyChangeEvent is generated
  512.      * however - for the "cellRenderer" property.
  513.      * <p>
  514.      * The default value of this property is provided by the ListUI
  515.      * delegate, i.e. by the look and feel implementation.
  516.      * <p>
  517.      * This is a JavaBeans bound property.
  518.      *
  519.      * @param cellRenderer the ListCellRenderer that paints list cells
  520.      * @see #getCellRenderer
  521.      * @beaninfo
  522.      *       bound: true
  523.      * description: The component used to draw the cells.
  524.      */
  525.     public void setCellRenderer(ListCellRenderer cellRenderer) {
  526.         ListCellRenderer oldValue = this.cellRenderer;
  527.         this.cellRenderer = cellRenderer;
  528.  
  529.         /* If the cellRenderer has changed and prototypeCellValue
  530.          * was set, then recompute fixedCellWidth and fixedCellHeight.
  531.          */
  532.         if ((cellRenderer != null) && !cellRenderer.equals(oldValue)) {
  533.             updateFixedCellSize();
  534.         }
  535.  
  536.         firePropertyChange("cellRenderer", oldValue, cellRenderer);
  537.     }
  538.  
  539.  
  540.     /**
  541.      * Returns the foreground color.
  542.      *
  543.      * @return the Color object for the foreground property
  544.      * @see #setSelectionForeground
  545.      * @see #setSelectionBackground
  546.      */
  547.     public Color getSelectionForeground() {
  548.         return selectionForeground;
  549.     }
  550.  
  551.  
  552.     /**
  553.      * Set the foreground color for selected cells.  Cell renderers
  554.      * can use this color to render text and graphics for selected
  555.      * cells.
  556.      * <p>
  557.      * The default value of this property is defined by the look
  558.      * and feel implementation.
  559.      * <p>
  560.      * This is a JavaBeans bound property.
  561.      *
  562.      * @param selectionForeground  the Color to use in the foreground
  563.      *                             for selected list items
  564.      * @see #getSelectionForeground
  565.      * @see #setSelectionBackground
  566.      * @see #setForeground
  567.      * @see #setBackground
  568.      * @see #setFont
  569.      * @beaninfo
  570.      *       bound: true
  571.      * description: The foreground color of selected cells.
  572.      */
  573.     public void setSelectionForeground(Color selectionForeground) {
  574.         Color oldValue = this.selectionForeground;
  575.         this.selectionForeground = selectionForeground;
  576.         firePropertyChange("selectionForeground", oldValue, selectionForeground);
  577.     }
  578.  
  579.  
  580.     /**
  581.      * Returns the background color for selected cells.
  582.      *
  583.      * @return the Color used for the background of selected list items
  584.      * @see #setSelectionBackground
  585.      * @see #setSelectionForeground
  586.      */
  587.     public Color getSelectionBackground() {
  588.         return selectionBackground;
  589.     }
  590.  
  591.  
  592.     /**
  593.      * Set the background color for selected cells.  Cell renderers
  594.      * can use this color to the fill selected cells.
  595.      * <p>
  596.      * The default value of this property is defined by the look
  597.      * and feel implementation.
  598.      * <p>
  599.      * This is a JavaBeans bound property.
  600.      *
  601.      * @param selectionBackground  the Color to use for the background
  602.      *                             of selected cells
  603.      * @see #getSelectionBackground
  604.      * @see #setSelectionForeground
  605.      * @see #setForeground
  606.      * @see #setBackground
  607.      * @see #setFont
  608.      * @beaninfo
  609.      *       bound: true
  610.      * description: The background color of selected cells.
  611.      */
  612.     public void setSelectionBackground(Color selectionBackground) {
  613.         Color oldValue = this.selectionBackground;
  614.         this.selectionBackground = selectionBackground;
  615.         firePropertyChange("selectionBackground", oldValue, selectionBackground);
  616.     }
  617.  
  618.  
  619.     /**
  620.      * Return the preferred number of visible rows.
  621.      *
  622.      * @return an int indicating the preferred number of rows to display
  623.      *         without using a scrollbar
  624.      * @see #setVisibleRowCount
  625.      */
  626.     public int getVisibleRowCount() {
  627.         return visibleRowCount;
  628.     }
  629.  
  630.     /**
  631.      * Set the preferred number of rows in the list that can be displayed
  632.      * without a scollbar, as determined by the nearest JViewPort ancestor,
  633.      * if any.  The value of this property only affects the value of
  634.      * the JLists preferredScrollableViewportSize.
  635.      * <p>
  636.      * The default value of this property is 8.
  637.      * <p>
  638.      * This is a JavaBeans bound property.
  639.      *
  640.      * @param visibleRowCount  an int specifying the preferred number of
  641.      *                         visible rows
  642.      * @see #getVisibleRowCount
  643.      * @see JComponent#getVisibleRect
  644.      * @see JViewPort
  645.      * @beaninfo
  646.      *       bound: true
  647.      * description: The preferred number of cells that can be displayed without a scrollbar.
  648.      */
  649.     public void setVisibleRowCount(int visibleRowCount) {
  650.         int oldValue = this.visibleRowCount;
  651.         this.visibleRowCount = Math.max(0, visibleRowCount);
  652.         firePropertyChange("visibleRowCount", oldValue, visibleRowCount);
  653.     }
  654.  
  655.  
  656.     /**
  657.      * Return the index of the cell in the upper left corner of the JList
  658.      * or -1 if nothing is visible or the list is empty.  Note that this
  659.      * cell may only be partially visible.
  660.      *
  661.      * @return an int -- the index of the first visible cell.
  662.      * @see #getLastVisibleIndex
  663.      * @see JComponent#getVisibleRect
  664.      */
  665.     public int getFirstVisibleIndex() {
  666.         Point visibleUL = getVisibleRect().getLocation();
  667.         return locationToIndex(visibleUL);
  668.     }
  669.  
  670.  
  671.     /**
  672.      * Return the index of the cell in the lower right corner of the JList
  673.      * or -1 if nothing is visible or the list is empty.  Note that this
  674.      * cell may only be partially visible.
  675.      *
  676.      * @return an int -- the index of the last visible cell.
  677.      * @see #getLastVisibleIndex
  678.      * @see JComponent#getVisibleRect
  679.      */
  680.     public int getLastVisibleIndex() {
  681.         Rectangle r = getVisibleRect();
  682.         Point visibleLR = new Point((r.x + r.width) - 1, (r.y + r.height) - 1);
  683.         return locationToIndex(visibleLR);
  684.     }
  685.  
  686.  
  687.     /**
  688.      * If this JList is being displayed within a JViewport and the
  689.      * specified cell isn't completely visible, scroll the viewport.
  690.      *
  691.      * @param an int -- the index of the cell to make visible
  692.      * @see JComponent#scrollRectToVisible
  693.      * @see #getVisibleRect
  694.      */
  695.     public void ensureIndexIsVisible(int index) {
  696.         Rectangle cellBounds = getCellBounds(index, index);
  697.         if (cellBounds != null) {
  698.             scrollRectToVisible(cellBounds);
  699.         }
  700.     }
  701.  
  702.  
  703.     /**
  704.      * --- ListUI Delegations ---
  705.      */
  706.  
  707.  
  708.     /**
  709.      * Convert a point in JList coordinates to the index
  710.      * of the cell at that location.  Returns -1 if there's no
  711.      * cell the specified location.
  712.      *
  713.      * @param location The JList relative coordinates of the cell
  714.      * @return an int -- the index of the cell at the given location, or -1.
  715.      */
  716.     public int locationToIndex(Point location) {
  717.         ListUI ui = getUI();
  718.         return (ui != null) ? ui.locationToIndex(this, location) : -1;
  719.     }
  720.  
  721.  
  722.     /**
  723.      * Returns the origin of the specified item in JList
  724.      * coordinates, null if index isn't valid.
  725.      *
  726.      * @param index The index of the JList cell.
  727.      * @return The origin of the index'th cell.
  728.      */
  729.     public Point indexToLocation(int index) {
  730.         ListUI ui = getUI();
  731.         return (ui != null) ? ui.indexToLocation(this, index) : null;
  732.     }
  733.  
  734.  
  735.     /**
  736.      * Returns the bounds of the specified range of items in JList
  737.      * coordinates, null if index isn't valid.
  738.      *
  739.      * @param index1  the index of the first JList cell in the range
  740.      * @param index2  the index of the last JList cell in the range
  741.      * @return the bounds of the indexed cells
  742.      */
  743.     public Rectangle getCellBounds(int index1, int index2) {
  744.         ListUI ui = getUI();
  745.         return (ui != null) ? ui.getCellBounds(this, index1, index2) : null;
  746.     }
  747.  
  748.  
  749.     /**
  750.      * --- ListModel Support ---
  751.      */
  752.  
  753.  
  754.     /**
  755.      * Returns the data model that holds the list of items displayed
  756.      * by the JList component.
  757.      *
  758.      * @return the ListModel that provides the displayed list of items
  759.      * @see #setModel
  760.      */
  761.     public ListModel getModel() {
  762.         return dataModel;
  763.     }
  764.  
  765.     /**
  766.      * Sets the model that represents the contents or "value" of the
  767.      * list and clears the list selection after notifying PropertyChangeListeners.
  768.      * <p>
  769.      * This is a JavaBeans bound property.
  770.      *
  771.      * @param model  the ListModel that provides the list of items for display
  772.      * @see #getModel
  773.      * @beaninfo
  774.      *       bound: true
  775.      * description: The object that contains the data to be drawn by this JList.
  776.      */
  777.     public void setModel(ListModel model) {
  778.         ListModel oldValue = dataModel;
  779.         dataModel = model;
  780.         firePropertyChange("model", oldValue, dataModel);
  781.         clearSelection();
  782.     }
  783.  
  784.  
  785.     /**
  786.      * A convenience method that constructs a ListModel from an array of Objects
  787.      * and then applies setModel to it.
  788.      *
  789.      * @param listData an array of Objects containing the items to display
  790.      *                 in the list
  791.      * @see #setModel
  792.      */
  793.     public void setListData(final Object[] listData) {
  794.         setModel (
  795.             new AbstractListModel() {
  796.                 public int getSize() { return listData.length; }
  797.                 public Object getElementAt(int i) { return listData[i]; }
  798.             }
  799.         );
  800.     }
  801.  
  802.  
  803.     /**
  804.      * A convenience method that constructs a ListModel from a Vector
  805.      * and then applies setModel to it.
  806.      *
  807.      * @param listData a Vector containing the items to display in the list
  808.      * @see #setModel
  809.      */
  810.     public void setListData(final Vector listData) {
  811.         setModel (
  812.             new AbstractListModel() {
  813.                 public int getSize() { return listData.size(); }
  814.                 public Object getElementAt(int i) { return listData.elementAt(i); }
  815.             }
  816.         );
  817.     }
  818.  
  819.  
  820.     /**
  821.      * --- ListSelectionModel delegations and extensions ---
  822.      */
  823.  
  824.  
  825.     /**
  826.      * Returns an instance of DefaultListSelectionModel.  This
  827.      * method is used by the constructor to initialize the
  828.      * selectionModel property.
  829.      *
  830.      * @return The ListSelectionModel used by this JList.
  831.      * @see #setSelectionModel
  832.      * @see DefaultListSelectionModel
  833.      */
  834.     protected ListSelectionModel createSelectionModel() {
  835.         return new DefaultListSelectionModel();
  836.     }
  837.  
  838.  
  839.     /**
  840.      * Returns the value of the current selection model. The selection
  841.      * model handles the task of making single selections, selections
  842.      * of contiguous ranges, and non-contiguous selections.
  843.      *
  844.      * @return the ListSelectionModel that implements list selections
  845.      * @see #setSelectionModel
  846.      * @see ListSelectionModel
  847.      */
  848.     public ListSelectionModel getSelectionModel() {
  849.         return selectionModel;
  850.     }
  851.  
  852.  
  853.     /**
  854.      * This method notifies JList ListSelectionListeners that
  855.      * the selection model has changed.  It's used to forward
  856.      * ListSelectionEvents from the selectionModel to the
  857.      * ListSelectionListeners added directly to the JList.
  858.      *
  859.      * @see #addListSelectionListener
  860.      * @see #removeListSelectionListener
  861.      * @see EventListenerList
  862.      */
  863.     protected void fireSelectionValueChanged(int firstIndex, int lastIndex,
  864.                                              boolean isAdjusting)
  865.     {
  866.         Object[] listeners = listenerList.getListenerList();
  867.         ListSelectionEvent e = null;
  868.  
  869.         for (int i = listeners.length - 2; i >= 0; i -= 2) {
  870.             if (listeners[i] == ListSelectionListener.class) {
  871.                 if (e == null) {
  872.                     e = new ListSelectionEvent(this, firstIndex, lastIndex,
  873.                                                isAdjusting);
  874.                 }
  875.                 ((ListSelectionListener)listeners[i+1]).valueChanged(e);
  876.             }
  877.         }
  878.     }
  879.  
  880.  
  881.     /**
  882.      * Add a listener to the list that's notified each time a change
  883.      * to the selection occurs.  Listeners added directly to the JList
  884.      * will have their ListSelectionEvent.getSource() == this JList
  885.      * (instead of the ListSelectionModel).
  886.      *
  887.      * @param listener The ListSelectionListener to add.
  888.      * @see #getSelectionModel
  889.      */
  890.     public void addListSelectionListener(ListSelectionListener listener) {
  891.  
  892.         /* Lazily create a ListSelectionListener that forwards
  893.          * ListSelectionEvents from the selectionModel to the JList
  894.          * ListSelectionListeners.  The forwarded events only differ
  895.          * from the originals in that their source is the JList
  896.          * instead of the selectionModel itself.
  897.          */
  898.         if (selectionListener == null) {
  899.             selectionListener = new ListSelectionListener() {
  900.                 public void valueChanged(ListSelectionEvent e) {
  901.                     fireSelectionValueChanged(e.getFirstIndex(),
  902.                                               e.getLastIndex(),
  903.                                               e.getValueIsAdjusting());
  904.                 }
  905.             };
  906.             getSelectionModel().addListSelectionListener(selectionListener);
  907.         }
  908.  
  909.         listenerList.add(ListSelectionListener.class, listener);
  910.     }
  911.  
  912.  
  913.     /**
  914.      * Remove a listener from the list that's notified each time a
  915.      * change to the selection occurs.
  916.      *
  917.      * @param listener The ListSelectionListener to remove.
  918.      * @see #addListSelectionListener
  919.      * @see #getSelectionModel
  920.      */
  921.     public void removeListSelectionListener(ListSelectionListener listener) {
  922.         listenerList.remove(ListSelectionListener.class, listener);
  923.     }
  924.  
  925.  
  926.     /**
  927.      * Set the selectionModel for the list to a non-null ListSelectionModel
  928.      * implementation. The selection model handles the task of making single
  929.      * selections, selections of contiguous ranges, and non-contiguous
  930.      * selections.
  931.      * <p>
  932.      * This is a JavaBeans bound property.
  933.      *
  934.      * @return selectionModel  the ListSelectionModel that implements
  935.      *                         list selections
  936.      * @see #getSelectionModel
  937.      * @beaninfo
  938.      *       bound: true
  939.      * description: The selection model, recording which cells are selected.
  940.      */
  941.     public void setSelectionModel(ListSelectionModel selectionModel) {
  942.         if (selectionModel == null) {
  943.             throw new IllegalArgumentException("selectionModel must be non null");
  944.         }
  945.  
  946.         /* Remove the forwarding ListSelectionListener from the old
  947.          * selectionModel, and add it to the new one, if neccessary.
  948.          */
  949.         if (selectionListener != null) {
  950.             this.selectionModel.removeListSelectionListener(selectionListener);
  951.             selectionModel.addListSelectionListener(selectionListener);
  952.         }
  953.  
  954.         ListSelectionModel oldValue = this.selectionModel;
  955.         this.selectionModel = selectionModel;
  956.         firePropertyChange("selectionModel", oldValue, selectionModel);
  957.  
  958.     if (accessibleContext != null) {
  959.             accessibleContext.firePropertyChange(
  960.             AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
  961.             new Boolean(false), new Boolean(true));
  962.     }
  963.     }
  964.  
  965.  
  966.     /**
  967.      * The following selectionMode values are allowed:
  968.      * <ul>
  969.      * <li> <code>SINGLE_SELECTION</code>
  970.      *   Only one list index can be selected at a time.  In this
  971.      *   mode the setSelectionInterval and addSelectionInterval
  972.      *   methods are equivalent, and they only the first index
  973.      *   argument is used.
  974.      * <li> <code>SINGLE_INTERVAL_SELECTION</code>
  975.      *   One contiguous index interval can be selected at a time.
  976.      *   In this mode setSelectionInterval and addSelectionInterval
  977.      *   are equivalent.
  978.      * <li> <code>MULTIPLE_INTERVAL_SELECTION</code>
  979.      *   In this mode, there's no restriction on what can be selected.
  980.      * </ul>
  981.      *
  982.      * @see #getSelectionMode
  983.      * @beaninfo
  984.      * description: The selection mode.
  985.      *        enum: SINGLE_SELECTION            ListSelectionModel.SINGLE_SELECTION
  986.      *              SINGLE_INTERVAL_SELECTION   ListSelectionModel.SINGLE_INTERVAL_SELECTION
  987.      *              MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
  988.      */
  989.     public void setSelectionMode(int selectionMode) {
  990.     getSelectionModel().setSelectionMode(selectionMode);
  991.     }
  992.  
  993.     /**
  994.      * @return The value of the selectionMode property.
  995.      * @see #setSelectionMode
  996.      */
  997.     public int getSelectionMode() {
  998.     return getSelectionModel().getSelectionMode();
  999.     }
  1000.  
  1001.  
  1002.     /**
  1003.      * Returns the first index argument from the most recent addSelectionInterval
  1004.      * or setSelectionInterval call.
  1005.      * This is a convenience method that just delegates to the selectionModel.
  1006.      *
  1007.      * @return The index that most recently anchored an interval selection.
  1008.      * @see ListSelectionModel#getAnchorSelectionIndex
  1009.      * @see #addSelectionInterval
  1010.      * @see #setSelectionInterval
  1011.      * @see #addListSelectionListener
  1012.      */
  1013.     public int getAnchorSelectionIndex() {
  1014.         return getSelectionModel().getAnchorSelectionIndex();
  1015.     }
  1016.  
  1017.  
  1018.     /**
  1019.      * Returns the second index argument from the most recent addSelectionInterval
  1020.      * or setSelectionInterval call.
  1021.      * This is a convenience method that just  delegates to the selectionModel.
  1022.      *
  1023.      * @return The index that most recently ended a interval selection.
  1024.      * @see ListSelectionModel#getLeadSelectionIndex
  1025.      * @see #addSelectionInterval
  1026.      * @see #setSelectionInterval
  1027.      * @see #addListSelectionListener
  1028.      * @beaninfo
  1029.      * description: The lead selection index.
  1030.      */
  1031.     public int getLeadSelectionIndex() {
  1032.         return getSelectionModel().getLeadSelectionIndex();
  1033.     }
  1034.  
  1035.  
  1036.     /**
  1037.      * Returns the smallest selected cell index.
  1038.      * This is a convenience method that just delegates to the selectionModel.
  1039.      *
  1040.      * @return The smallest selected cell index.
  1041.      * @see ListSelectionModel#getMinSelectionIndex
  1042.      * @see #addListSelectionListener
  1043.      */
  1044.     public int getMinSelectionIndex() {
  1045.         return getSelectionModel().getMinSelectionIndex();
  1046.     }
  1047.  
  1048.  
  1049.     /**
  1050.      * Returns the largest selected cell index.
  1051.      * This is a convenience method that just delegates to the selectionModel.
  1052.      *
  1053.      * @return The largest selected cell index.
  1054.      * @see ListSelectionModel#getMaxSelectionIndex
  1055.      * @see #addListSelectionListener
  1056.      */
  1057.     public int getMaxSelectionIndex() {
  1058.         return getSelectionModel().getMaxSelectionIndex();
  1059.     }
  1060.  
  1061.  
  1062.     /**
  1063.      * Returns true if the specified index is selected.
  1064.      * This is a convenience method that just delegates to the selectionModel.
  1065.      *
  1066.      * @return True if the specified index is selected.
  1067.      * @see ListSelectionModel#isSelectedIndex
  1068.      * @see #setSelectedIndex
  1069.      * @see #addListSelectionListener
  1070.      */
  1071.     public boolean isSelectedIndex(int index) {
  1072.         return getSelectionModel().isSelectedIndex(index);
  1073.     }
  1074.  
  1075.  
  1076.     /**
  1077.      * Returns true if nothing is selected
  1078.      * This is a convenience method that just delegates to the selectionModel.
  1079.      *
  1080.      * @return True if nothing is selected
  1081.      * @see ListSelectionModel#isSelectionEmpty
  1082.      * @see clearSelection
  1083.      * @see #addListSelectionListener
  1084.      */
  1085.     public boolean isSelectionEmpty() {
  1086.         return getSelectionModel().isSelectionEmpty();
  1087.     }
  1088.  
  1089.  
  1090.     /**
  1091.      * Clears the selection - after calling this method isSelectionEmpty()
  1092.      * will return true.
  1093.      * This is a convenience method that just delegates to the selectionModel.
  1094.      *
  1095.      * @see ListSelectionModel#clearSelection
  1096.      * @see #isSelectionEmpty
  1097.      * @see #addListSelectionListener
  1098.      */
  1099.     public void clearSelection() {
  1100.         getSelectionModel().clearSelection();
  1101.     }
  1102.  
  1103.  
  1104.     /**
  1105.      * Select the specified interval.  Both the anchor and lead indices are
  1106.      * included.  It's not neccessary for anchor to be less than lead.
  1107.      * This is a convenience method that just delegates to the selectionModel.
  1108.      *
  1109.      * @param anchor The first index to select
  1110.      * @param lead The last index to select
  1111.      * @see ListSelectionModel#setSelectionInterval
  1112.      * @see #addSelectionInterval
  1113.      * @see #removeSelectionInterval
  1114.      * @see #addListSelectionListener
  1115.      */
  1116.     public void setSelectionInterval(int anchor, int lead) {
  1117.         getSelectionModel().setSelectionInterval(anchor, lead);
  1118.     }
  1119.  
  1120.  
  1121.     /**
  1122.      * Set the selection to be the union of the specified interval with current
  1123.      * selection.  Both the anchor and lead indices are
  1124.      * included.  It's not neccessary for anchor to be less than lead.
  1125.      * This is a convenience method that just delegates to the selectionModel.
  1126.      *
  1127.      * @param anchor The first index to add to the selection
  1128.      * @param lead The last index to add to the selection
  1129.      * @see ListSelectionModel#addSelectionInterval
  1130.      * @see #setSelectionInterval
  1131.      * @see #removeSelectionInterval
  1132.      * @see #addListSelectionListener
  1133.      */
  1134.     public void addSelectionInterval(int anchor, int lead) {
  1135.         getSelectionModel().addSelectionInterval(anchor, lead);
  1136.     }
  1137.  
  1138.  
  1139.     /**
  1140.      * Set the selection to be the set difference of the specified interval
  1141.      * and the current selection.  Both the anchor and lead indices are
  1142.      * removed.  It's not neccessary for anchor to be less than lead.
  1143.      * This is a convenience method that just delegates to the selectionModel.
  1144.      *
  1145.      * @param anchor The first index to remove from the selection
  1146.      * @param lead The last index to remove from the selection
  1147.      * @see ListSelectionModel#removeSelectionInterval
  1148.      * @see #setSelectionInterval
  1149.      * @see #addSelectionInterval
  1150.      * @see #addListSelectionListener
  1151.      */
  1152.     public void removeSelectionInterval(int index0, int index1) {
  1153.         getSelectionModel().removeSelectionInterval(index0, index1);
  1154.     }
  1155.  
  1156.  
  1157.     /**
  1158.      * Sets the data model's isAdjusting property true, so that
  1159.      * a single event will be generated when all of the selection
  1160.      * events have finished (for example, when the mouse is being
  1161.      * dragged over the list in selection mode).
  1162.      *
  1163.      * @param b the boolean value for the property value
  1164.      * @see ListSelectionModel#setValueIsAdjusting
  1165.      */
  1166.     public void setValueIsAdjusting(boolean b) {
  1167.         getSelectionModel().setValueIsAdjusting(b);
  1168.     }
  1169.  
  1170.  
  1171.     /**
  1172.      * Returns the value of the data model's isAdjusting property.
  1173.      * This value is true if multiple changes are being made.
  1174.      *
  1175.      * @return true if multiple selection-changes are occuring, as
  1176.      *         when the mouse is being dragged over the list
  1177.      * @see ListSelectionModel#getValueIsAdjusting
  1178.      */
  1179.     public boolean getValueIsAdjusting() {
  1180.         return getSelectionModel().getValueIsAdjusting();
  1181.     }
  1182.  
  1183.  
  1184.     /**
  1185.      * Return an array of all of the selected indices in increasing
  1186.      * order.
  1187.      *
  1188.      * @return All of the selected indices, in increasing order.
  1189.      * @see #removeSelectionInterval
  1190.      * @see #addListSelectionListener
  1191.      */
  1192.     public int[] getSelectedIndices() {
  1193.         ListSelectionModel sm = getSelectionModel();
  1194.         int iMin = sm.getMinSelectionIndex();
  1195.         int iMax = sm.getMaxSelectionIndex();
  1196.  
  1197.         if ((iMin < 0) || (iMax < 0)) {
  1198.             return new int[0];
  1199.         }
  1200.  
  1201.         int[] rvTmp = new int[1+ (iMax - iMin)];
  1202.         int n = 0;
  1203.         for(int i = iMin; i <= iMax; i++) {
  1204.             if (sm.isSelectedIndex(i)) {
  1205.                 rvTmp[n++] = i;
  1206.             }
  1207.         }
  1208.         int[] rv = new int[n];
  1209.         System.arraycopy(rvTmp, 0, rv, 0, n);
  1210.         return rv;
  1211.     }
  1212.  
  1213.  
  1214.     /**
  1215.      * Select a single cell.
  1216.      *
  1217.      * @param index The index of the one cell to select
  1218.      * @see ListSelectionModel#setSelectionInterval
  1219.      * @see #isSelectedIndex
  1220.      * @see #addListSelectionListener
  1221.      * @beaninfo
  1222.      * description: The index of the selected cell.
  1223.      */
  1224.     public void setSelectedIndex(int index) {
  1225.         getSelectionModel().setSelectionInterval(index, index);
  1226.     }
  1227.  
  1228.  
  1229.     /**
  1230.      * Select a set of cells.
  1231.      *
  1232.      * @param indices The indices of the cells to select
  1233.      * @see ListSelectionModel#addSelectionInterval
  1234.      * @see #isSelectedIndex
  1235.      * @see #addListSelectionListener
  1236.      */
  1237.     public void setSelectedIndices(int[] indices) {
  1238.         ListSelectionModel sm = getSelectionModel();
  1239.         sm.clearSelection();
  1240.         for(int i = 0; i < indices.length; i++) {
  1241.             sm.addSelectionInterval(indices[i], indices[i]);
  1242.         }
  1243.     }
  1244.  
  1245.  
  1246.     /**
  1247.      * Return an array of the values for the selected cells.
  1248.      * The returned values are sorted in increasing index order.
  1249.      *
  1250.      * @return the selected values
  1251.      * @see #isSelectedIndex
  1252.      * @see #getModel
  1253.      * @see #addListSelectionListener
  1254.      */
  1255.     public Object[] getSelectedValues() {
  1256.         ListSelectionModel sm = getSelectionModel();
  1257.         ListModel dm = getModel();
  1258.  
  1259.         int iMin = sm.getMinSelectionIndex();
  1260.         int iMax = sm.getMaxSelectionIndex();
  1261.  
  1262.         if ((iMin < 0) || (iMax < 0)) {
  1263.             return new Object[0];
  1264.         }
  1265.  
  1266.         Object[] rvTmp = new Object[1+ (iMax - iMin)];
  1267.         int n = 0;
  1268.         for(int i = iMin; i <= iMax; i++) {
  1269.             if (sm.isSelectedIndex(i)) {
  1270.                 rvTmp[n++] = dm.getElementAt(i);
  1271.             }
  1272.         }
  1273.         Object[] rv = new Object[n];
  1274.         System.arraycopy(rvTmp, 0, rv, 0, n);
  1275.         return rv;
  1276.     }
  1277.  
  1278.  
  1279.     /**
  1280.      * A convenience method that returns the first selected index.
  1281.      *
  1282.      * @return The first selected index.
  1283.      * @see #getMinSelectionIndex
  1284.      * @see #addListSelectionListener
  1285.      */
  1286.     public int getSelectedIndex() {
  1287.         return getMinSelectionIndex();
  1288.     }
  1289.  
  1290.  
  1291.     /**
  1292.      * A convenience method that returns the first selected value
  1293.      * or null, if the selection is empty.
  1294.      *
  1295.      * @return The first selected value.
  1296.      * @see #getMinSelectionIndex
  1297.      * @see #getModel
  1298.      * @see #addListSelectionListener
  1299.      */
  1300.     public Object getSelectedValue() {
  1301.         int i = getMinSelectionIndex();
  1302.         return (i == -1) ? null : getModel().getElementAt(i);
  1303.     }
  1304.  
  1305.  
  1306.     // PENDING(hmuller) this should move to BasicComboBoxUI
  1307.     public void setSelectedValue(Object anObject,boolean shouldScroll) {
  1308.         if(anObject == null)
  1309.             setSelectedIndex(-1);
  1310.         else if(!anObject.equals(getSelectedValue())) {
  1311.             int i,c;
  1312.             ListModel dm = getModel();
  1313.             for(i=0,c=dm.getSize();i<c;i++)
  1314.                 if(anObject.equals(dm.getElementAt(i))){
  1315.                     setSelectedIndex(i);
  1316.                     if(shouldScroll)
  1317.                         ensureIndexIsVisible(i);
  1318.                     repaint();  /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
  1319.                     return;
  1320.                 }
  1321.             setSelectedIndex(-1);
  1322.         }
  1323.         repaint(); /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
  1324.     }
  1325.  
  1326.  
  1327.  
  1328.     /**
  1329.      * --- The Scrollable Implementation ---
  1330.      */
  1331.  
  1332.     /**
  1333.      * Compute the size of the viewport needed to display visibleRowCount
  1334.      * rows.  This is trivial if fixedCellWidth and fixedCellHeight
  1335.      * were specified.  Note that they can specified implicitly with
  1336.      * the prototypeCellValue property.  If fixedCellWidth wasn't specified,
  1337.      * it's computed by finding the widest list element.  If fixedCellHeight
  1338.      * wasn't specified then we resort to heuristics:
  1339.      * <ul>
  1340.      * <li>
  1341.      * If the model isn't empty we just multiply the height of the first row
  1342.      * by visibleRowCount.
  1343.      * <li>
  1344.      * If the model is empty, i.e. JList.getModel().getSize() == 0, then
  1345.      * we just allocate 16 pixels per visible row, and 256 pixels
  1346.      * for the width (unless fixedCellWidth was set), and hope for the best.
  1347.      * </ul>
  1348.      *
  1349.      * @see #getPreferredScrollableViewportSize
  1350.      * @see #setPrototypeCellValue
  1351.      */
  1352.     public Dimension getPreferredScrollableViewportSize()
  1353.     {
  1354.         Insets insets = getInsets();
  1355.         int dx = insets.left + insets.right;
  1356.         int dy = insets.top + insets.bottom;
  1357.  
  1358.         int visibleRowCount = getVisibleRowCount();
  1359.         int fixedCellWidth = getFixedCellWidth();
  1360.         int fixedCellHeight = getFixedCellHeight();
  1361.  
  1362.         if ((fixedCellWidth > 0) && (fixedCellHeight > 0)) {
  1363.             int width = fixedCellWidth + dx;
  1364.             int height = (visibleRowCount * fixedCellHeight) + dy;
  1365.             return new Dimension(width, height);
  1366.         }
  1367.         else if (getModel().getSize() > 0) {
  1368.             int width = getPreferredSize().width;
  1369.             Rectangle r = getCellBounds(0, 0);
  1370.             int height = (visibleRowCount * r.height) + dy;
  1371.             return new Dimension(width, height);
  1372.         }
  1373.         else {
  1374.             fixedCellWidth = (fixedCellWidth > 0) ? fixedCellWidth : 256;
  1375.             fixedCellHeight = (fixedCellHeight > 0) ? fixedCellHeight : 16;
  1376.             return new Dimension(fixedCellWidth, fixedCellHeight * visibleRowCount);
  1377.         }
  1378.     }
  1379.  
  1380.  
  1381.     /**
  1382.      * If we're scrolling downwards (<code>direction</code> is
  1383.      * greater than 0), and the first row is completely visible with respect
  1384.      * to <code>visibleRect</code>, then return its height.  If
  1385.      * we're scrolling downwards and the first row is only partially visible,
  1386.      * return the height of the visible part of the first row.  Similarly
  1387.      * if we're scrolling upwards we return the height of the row above
  1388.      * the first row, unless the first row is partially visible.
  1389.      *
  1390.      * @return The distance to scroll to expose the next or previous row.
  1391.      * @see Scrollable#getScrollableUnitIncrement
  1392.      */
  1393.     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
  1394.     {
  1395.         if (orientation == SwingConstants.HORIZONTAL) {
  1396.             return 1;
  1397.         }
  1398.         else {
  1399.             int row = getFirstVisibleIndex();
  1400.  
  1401.             if (row == -1) {
  1402.                 return 0;
  1403.             }
  1404.             else {
  1405.                 /* Scroll Down */
  1406.                 if (direction > 0) {
  1407.                     Rectangle r = getCellBounds(row, row);
  1408.                     return (r == null) ? 0 : r.height - (visibleRect.y - r.y);
  1409.                 }
  1410.                 /* Scroll Up */
  1411.                 else {
  1412.                     Rectangle r = getCellBounds(row, row);
  1413.  
  1414.                     /* The first row is completely visible and it's row 0.
  1415.                      * We're done.
  1416.                      */
  1417.                     if ((r.y == visibleRect.y) && (row == 0))  {
  1418.                         return 0;
  1419.                     }
  1420.                     /* The first row is completely visible, return the
  1421.                      * height of the previous row.
  1422.                      */
  1423.                     else if (r.y == visibleRect.y) {
  1424.                         Rectangle prevR = getCellBounds(row - 1, row - 1);
  1425.                         return (prevR== null) ? 0 : prevR.height;
  1426.                     }
  1427.                     /* The first row is partially visible, return the
  1428.                      * height of hidden part.
  1429.                      */
  1430.                     else {
  1431.                         return visibleRect.y - r.y;
  1432.                     }
  1433.                 }
  1434.             }
  1435.         }
  1436.     }
  1437.  
  1438.  
  1439.     /**
  1440.      * @return The visibleRect.height or visibleRect.width per the orientation.
  1441.      * @see Scrollable#getScrollableUnitIncrement
  1442.      */
  1443.     public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
  1444.         return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : visibleRect.width;
  1445.     }
  1446.  
  1447.  
  1448.     /**
  1449.      * If this JList is displayed in a JViewport, don't change its width
  1450.      * when the viewports width changes.  This allows horizontal
  1451.      * scrolling if the JViewport is itself embedded in a JScrollPane.
  1452.      *
  1453.      * @return False - don't track the viewports width.
  1454.      * @see Scrollable#getScrollableTracksViewportWidth
  1455.      */
  1456.     public boolean getScrollableTracksViewportWidth() {
  1457.         return false;
  1458.     }
  1459.  
  1460.     /**
  1461.      * If this JList is displayed in a JViewport, don't change its height
  1462.      * when the viewports height changes.  This allows vertical
  1463.      * scrolling if the JViewport is itself embedded in a JScrollPane.
  1464.      *
  1465.      * @return False - don't track the viewports width.
  1466.      * @see Scrollable#getScrollableTracksViewportWidth
  1467.      */
  1468.     public boolean getScrollableTracksViewportHeight() {
  1469.         return false;
  1470.     }
  1471.  
  1472.  
  1473.  
  1474.     /**
  1475.      * --- Accessibility Support ---
  1476.      */
  1477.  
  1478.     /**
  1479.      * Get the AccessibleContext associated with this JComponent
  1480.      *
  1481.      * @return the AccessibleContext of this JComponent
  1482.      */
  1483.     public AccessibleContext getAccessibleContext() {
  1484.         if (accessibleContext == null) {
  1485.             accessibleContext = new AccessibleJList();
  1486.         }
  1487.         return accessibleContext;
  1488.     }
  1489.  
  1490.     /**
  1491.      * The class used to obtain the accessible role for this object.
  1492.      * <p>
  1493.      * Warning: serialized objects of this class will not be compatible with
  1494.      * future swing releases.  The current serialization support is appropriate
  1495.      * for short term storage or RMI between Swing1.0 applications.  It will
  1496.      * not be possible to load serialized Swing1.0 objects with future releases
  1497.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1498.      * baseline for the serialized form of Swing objects.
  1499.      */
  1500.     protected class AccessibleJList extends AccessibleJComponent
  1501.         implements AccessibleSelection, ListSelectionListener, ListDataListener {
  1502.  
  1503.         AccessibleJList() {
  1504.             super();
  1505.             JList.this.getSelectionModel().addListSelectionListener(this);
  1506.             JList.this.getModel().addListDataListener(this);
  1507.         }
  1508.  
  1509.         /**
  1510.          * List Selection Listener value change method. Used to fire the property change
  1511.          *
  1512.          * @param e ListSelectionEvent
  1513.          *
  1514.          */
  1515.         public void valueChanged(ListSelectionEvent e) {
  1516.  
  1517.             firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  1518.                    new Boolean(false), new Boolean(true));
  1519.             firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
  1520.                    new Boolean(false), new Boolean(true));
  1521.  
  1522.             // Process the State changes for Multiselectable
  1523.             AccessibleStateSet s = getAccessibleStateSet();
  1524.             ListSelectionModel lsm = JList.this.getSelectionModel();
  1525.             if (lsm.getSelectionMode() != ListSelectionModel.SINGLE_SELECTION) {
  1526.                 if (!s.contains(AccessibleState.MULTISELECTABLE)) {
  1527.                     s.add(AccessibleState.MULTISELECTABLE);
  1528.                     firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1529.                        null, AccessibleState.MULTISELECTABLE);
  1530.                 }
  1531.             } else {
  1532.                 if (s.contains(AccessibleState.MULTISELECTABLE)) {
  1533.                     s.remove(AccessibleState.MULTISELECTABLE);
  1534.                     firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1535.                        AccessibleState.MULTISELECTABLE, null);
  1536.                 }
  1537.             }
  1538.         }
  1539.  
  1540.         /**
  1541.          * List Data Listener interval added method. Used to fire the visible data property change
  1542.          *
  1543.          * @param e ListDataEvent
  1544.          *
  1545.          */
  1546.         public void intervalAdded(ListDataEvent e) {
  1547.             firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  1548.                        new Boolean(false), new Boolean(true));
  1549.         }
  1550.  
  1551.         /**
  1552.          * List Data Listener interval removed method. Used to fire the visible data property change
  1553.          *
  1554.          * @param e ListDataEvent
  1555.          *
  1556.          */
  1557.     public void intervalRemoved(ListDataEvent e) {
  1558.             firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  1559.                    new Boolean(false), new Boolean(true));
  1560.         }
  1561.  
  1562.         /**
  1563.          * List Data Listener contents changed method. Used to fire the visible data property change
  1564.          *
  1565.          * @param e ListDataEvent
  1566.          *
  1567.          */
  1568.          public void contentsChanged(ListDataEvent e) {
  1569.              firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  1570.                 new Boolean(false), new Boolean(true));
  1571.          }
  1572.  
  1573.     // AccessibleContext methods
  1574.  
  1575.         /**
  1576.          * Get the state set of this object.
  1577.          *
  1578.          * @return an instance of AccessibleState containing the current state
  1579.          * of the object
  1580.          * @see AccessibleState
  1581.          */
  1582.         public AccessibleStateSet getAccessibleStateSet() {
  1583.             AccessibleStateSet states = super.getAccessibleStateSet();
  1584.         if (selectionModel.getSelectionMode() !=
  1585.         ListSelectionModel.SINGLE_SELECTION) {
  1586.         states.add(AccessibleState.MULTISELECTABLE);
  1587.         }
  1588.             return states;
  1589.         }
  1590.  
  1591.         /**
  1592.          * Get the role of this object.
  1593.          *
  1594.          * @return an instance of AccessibleRole describing the role of the
  1595.          * object
  1596.          * @see AccessibleRole
  1597.          */
  1598.         public AccessibleRole getAccessibleRole() {
  1599.             return AccessibleRole.LIST;
  1600.         }
  1601.  
  1602.         /**
  1603.          * Returns the Accessible child contained at the local coordinate
  1604.          * Point, if one exists.
  1605.          *
  1606.          * @return the Accessible at the specified location, if it exists
  1607.          */
  1608.         public Accessible getAccessibleAt(Point p) {
  1609.             int i = locationToIndex(p);
  1610.             if (i >= 0) {
  1611.                 return new AccessibleJListChild(JList.this, i);
  1612.             } else {
  1613.                 return null;
  1614.             }
  1615.         }
  1616.  
  1617.         /**
  1618.          * Returns the number of accessible children in the object.  If all
  1619.          * of the children of this object implement Accessible, than this
  1620.          * method should return the number of children of this object.
  1621.          *
  1622.          * @return the number of accessible children in the object.
  1623.          */
  1624.         public int getAccessibleChildrenCount() {
  1625.             return getModel().getSize();
  1626.         }
  1627.  
  1628.         /**
  1629.          * Return the nth Accessible child of the object.
  1630.          *
  1631.          * @param i zero-based index of child
  1632.          * @return the nth Accessible child of the object
  1633.          */
  1634.         public Accessible getAccessibleChild(int i) {
  1635.             if (i >= getModel().getSize()) {
  1636.                 return null;
  1637.             } else {
  1638.                 return new AccessibleJListChild(JList.this, i);
  1639.             }
  1640.         }
  1641.  
  1642.     /**
  1643.      * Get the AccessibleSelection associated with this object if one
  1644.      * exists.  Otherwise return null.
  1645.      */
  1646.     public AccessibleSelection getAccessibleSelection() {
  1647.         return this;
  1648.     }
  1649.  
  1650.  
  1651.     // AccessibleSelection methods
  1652.  
  1653.         /**
  1654.          * Returns the number of items currently selected.
  1655.          * If no items are selected, the return value will be 0.
  1656.          *
  1657.          * @return the number of items currently selected.
  1658.          */
  1659.          public int getAccessibleSelectionCount() {
  1660.              return JList.this.getSelectedIndices().length;
  1661.          }
  1662.  
  1663.         /**
  1664.          * Returns an Accessible representing the specified selected item
  1665.          * in the object.  If there isn't a selection, or there are
  1666.          * fewer items selcted than the integer passed in, the return
  1667.          * value will be null.
  1668.          *
  1669.          * @param i the zero-based index of selected items
  1670.          * @return an Accessible containing the selected item
  1671.          */
  1672.          public Accessible getAccessibleSelection(int i) {
  1673.              int len = getAccessibleSelectionCount();
  1674.              if (i < 0 || i >= len) {
  1675.                  return null;
  1676.              } else {
  1677.                  return getAccessibleChild(JList.this.getSelectedIndices()[i]);
  1678.              }
  1679.          }
  1680.  
  1681.         /**
  1682.          * Returns true if the current child of this object is selected.
  1683.          *
  1684.          * @param i the zero-based index of the child in this Accessible
  1685.      * object.
  1686.          * @see AccessibleContext#getAccessibleChild
  1687.          */
  1688.         public boolean isAccessibleChildSelected(int i) {
  1689.         return isSelectedIndex(i);
  1690.     }
  1691.  
  1692.         /**
  1693.          * Adds the specified selected item in the object to the object's
  1694.          * selection.  If the object supports multiple selections,
  1695.          * the specified item is added to any existing selection, otherwise
  1696.          * it replaces any existing selection in the object.  If the
  1697.          * specified item is already selected, this method has no effect.
  1698.          *
  1699.          * @param i the zero-based index of selectable items
  1700.          */
  1701.          public void addAccessibleSelection(int i) {
  1702.              JList.this.addSelectionInterval(i, i);
  1703.          }
  1704.  
  1705.         /**
  1706.          * Removes the specified selected item in the object from the object's
  1707.          * selection.  If the specified item isn't currently selected, this
  1708.          * method has no effect.
  1709.          *
  1710.          * @param i the zero-based index of selectable items
  1711.          */
  1712.          public void removeAccessibleSelection(int i) {
  1713.              JList.this.removeSelectionInterval(i, i);
  1714.          }
  1715.  
  1716.         /**
  1717.          * Clears the selection in the object, so that nothing in the
  1718.          * object is selected.
  1719.          */
  1720.          public void clearAccessibleSelection() {
  1721.              JList.this.clearSelection();
  1722.          }
  1723.  
  1724.         /**
  1725.          * Causes every selected item in the object to be selected
  1726.          * if the object supports multiple selections.
  1727.          */
  1728.          public void selectAllAccessibleSelection() {
  1729.              JList.this.addSelectionInterval(0, getAccessibleChildrenCount() -1);
  1730.          }
  1731.  
  1732.  
  1733.         protected class AccessibleJListChild extends AccessibleContext
  1734.                 implements Accessible, AccessibleComponent {
  1735.             private JList     parent = null;
  1736.             private int       indexInParent;
  1737.             private Component component = null;
  1738.             private AccessibleContext accessibleContext = null;
  1739.             private ListModel listModel;
  1740.             private ListCellRenderer cellRenderer = null;
  1741.  
  1742.             public AccessibleJListChild(JList parent, int indexInParent) {
  1743.                 this.parent = parent;
  1744.                 this.setAccessibleParent(parent);
  1745.                 this.indexInParent = indexInParent;
  1746.                 if (parent != null) {
  1747.                     listModel = parent.getModel();
  1748.                     cellRenderer = parent.getCellRenderer();
  1749.                 }
  1750.             }
  1751.  
  1752.             private Component getCurrentComponent() {
  1753.                 return getComponentAtIndex(indexInParent);
  1754.             }
  1755.  
  1756.             private AccessibleContext getCurrentAccessibleContext() {
  1757.                 Component c = getComponentAtIndex(indexInParent);
  1758.                 if (c instanceof Accessible) {
  1759.                     return ((Accessible) c).getAccessibleContext();
  1760.                 } else {
  1761.                     return null;
  1762.                 }
  1763.             }
  1764.  
  1765.             private Component getComponentAtIndex(int index) {
  1766.                 if (index < 0 || index >= listModel.getSize()) {
  1767.                     return null;
  1768.                 }
  1769.                 if ((parent != null)
  1770.                         && (listModel != null)
  1771.                         && cellRenderer != null) {
  1772.                     Object value = listModel.getElementAt(index);
  1773.                     boolean isSelected = parent.isSelectedIndex(index);
  1774.                     boolean isFocussed = parent.hasFocus()
  1775.                             && (index == parent.getLeadSelectionIndex());
  1776.                     return cellRenderer.getListCellRendererComponent(
  1777.                             parent,
  1778.                             value,
  1779.                             index,
  1780.                             isSelected,
  1781.                             isFocussed);
  1782.                 } else {
  1783.                     return null;
  1784.                 }
  1785.             }
  1786.  
  1787.  
  1788.             // Accessible Methods
  1789.  
  1790.             public AccessibleContext getAccessibleContext() {
  1791.                 return this;
  1792.             }
  1793.  
  1794.  
  1795.             // AccessibleContext methods
  1796.  
  1797.             public String getAccessibleName() {
  1798.                 AccessibleContext ac = getCurrentAccessibleContext();
  1799.                 if (ac != null) {
  1800.                     return ac.getAccessibleName();
  1801.                 } else {
  1802.                     return null;
  1803.                 }
  1804.             }
  1805.  
  1806.             public void setAccessibleName(String s) {
  1807.                 AccessibleContext ac = getCurrentAccessibleContext();
  1808.                 if (ac != null) {
  1809.                     ac.setAccessibleName(s);
  1810.                 }
  1811.             }
  1812.  
  1813.             public String getAccessibleDescription() {
  1814.                 AccessibleContext ac = getCurrentAccessibleContext();
  1815.                 if (ac != null) {
  1816.                     return ac.getAccessibleDescription();
  1817.                 } else {
  1818.                     return null;
  1819.                 }
  1820.             }
  1821.  
  1822.             public void setAccessibleDescription(String s) {
  1823.                 AccessibleContext ac = getCurrentAccessibleContext();
  1824.                 if (ac != null) {
  1825.                     ac.setAccessibleDescription(s);
  1826.                 }
  1827.             }
  1828.  
  1829.             public AccessibleRole getAccessibleRole() {
  1830.                 AccessibleContext ac = getCurrentAccessibleContext();
  1831.                 if (ac != null) {
  1832.                     return ac.getAccessibleRole();
  1833.                 } else {
  1834.                     return null;
  1835.                 }
  1836.             }
  1837.  
  1838.             public AccessibleStateSet getAccessibleStateSet() {
  1839.                 AccessibleContext ac = getCurrentAccessibleContext();
  1840.                 AccessibleStateSet s;
  1841.                 if (ac != null) {
  1842.                     s = ac.getAccessibleStateSet();
  1843.                 } else {
  1844.                     s = new AccessibleStateSet();
  1845.                 }
  1846.                 s = ac.getAccessibleStateSet();
  1847.                 s.add(AccessibleState.SELECTABLE);
  1848.                 if (parent.isSelectedIndex(indexInParent)) {
  1849.                     s.add(AccessibleState.SELECTED);
  1850.                 }
  1851.                 if (this.isShowing()) {
  1852.                     s.add(AccessibleState.SHOWING);
  1853.                 } else if (s.contains(AccessibleState.SHOWING)) {
  1854.                     s.remove(AccessibleState.SHOWING);
  1855.         }
  1856.                 if (this.isVisible()) {
  1857.                     s.add(AccessibleState.VISIBLE);
  1858.                 } else if (s.contains(AccessibleState.VISIBLE)) {
  1859.                     s.remove(AccessibleState.VISIBLE);
  1860.         }
  1861.                 return s;
  1862.             }
  1863.  
  1864.             public int getAccessibleIndexInParent() {
  1865.                 return indexInParent;
  1866.             }
  1867.  
  1868.             public int getAccessibleChildrenCount() {
  1869.                 AccessibleContext ac = getCurrentAccessibleContext();
  1870.                 if (ac != null) {
  1871.                     return ac.getAccessibleChildrenCount();
  1872.                 } else {
  1873.                     return 0;
  1874.                 }
  1875.             }
  1876.  
  1877.             public Accessible getAccessibleChild(int i) {
  1878.                 AccessibleContext ac = getCurrentAccessibleContext();
  1879.                 if (ac != null) {
  1880.                     Accessible accessibleChild = ac.getAccessibleChild(i);
  1881.                     ac.setAccessibleParent(this);
  1882.                     return accessibleChild;
  1883.                 } else {
  1884.                     return null;
  1885.                 }
  1886.             }
  1887.  
  1888.             public Locale getLocale() {
  1889.                 AccessibleContext ac = getCurrentAccessibleContext();
  1890.                 if (ac != null) {
  1891.                     return ac.getLocale();
  1892.                 } else {
  1893.                     return null;
  1894.                 }
  1895.             }
  1896.  
  1897.             public void addPropertyChangeListener(PropertyChangeListener l) {
  1898.                 AccessibleContext ac = getCurrentAccessibleContext();
  1899.                 if (ac != null) {
  1900.                     ac.addPropertyChangeListener(l);
  1901.                 }
  1902.             }
  1903.  
  1904.             public void removePropertyChangeListener(PropertyChangeListener l) {
  1905.                 AccessibleContext ac = getCurrentAccessibleContext();
  1906.                 if (ac != null) {
  1907.                     ac.removePropertyChangeListener(l);
  1908.                 }
  1909.             }
  1910.  
  1911.             public AccessibleAction getAccessibleAction() {
  1912.                 return getCurrentAccessibleContext().getAccessibleAction();
  1913.             }
  1914.  
  1915.             public AccessibleComponent getAccessibleComponent() {
  1916.                 return this; // to override getBounds()
  1917.             }
  1918.  
  1919.             public AccessibleSelection getAccessibleSelection() {
  1920.                 return getCurrentAccessibleContext().getAccessibleSelection();
  1921.             }
  1922.  
  1923.             public AccessibleText getAccessibleText() {
  1924.                 return getCurrentAccessibleContext().getAccessibleText();
  1925.             }
  1926.  
  1927.             public AccessibleValue getAccessibleValue() {
  1928.                 return getCurrentAccessibleContext().getAccessibleValue();
  1929.             }
  1930.  
  1931.  
  1932.             // AccessibleComponent methods
  1933.  
  1934.             public Color getBackground() {
  1935.                 AccessibleContext ac = getCurrentAccessibleContext();
  1936.                 if (ac instanceof AccessibleComponent) {
  1937.                     return ((AccessibleComponent) ac).getBackground();
  1938.                 } else {
  1939.                     Component c = getCurrentComponent();
  1940.                     if (c != null) {
  1941.                         return c.getBackground();
  1942.                     } else {
  1943.                         return null;
  1944.                     }
  1945.                 }
  1946.             }
  1947.  
  1948.             public void setBackground(Color c) {
  1949.                 AccessibleContext ac = getCurrentAccessibleContext();
  1950.                 if (ac instanceof AccessibleComponent) {
  1951.                     ((AccessibleComponent) ac).setBackground(c);
  1952.                 } else {
  1953.                     Component cp = getCurrentComponent();
  1954.                     if (cp != null) {
  1955.                         cp.setBackground(c);
  1956.                     }
  1957.                 }
  1958.             }
  1959.  
  1960.             public Color getForeground() {
  1961.                 AccessibleContext ac = getCurrentAccessibleContext();
  1962.                 if (ac instanceof AccessibleComponent) {
  1963.                     return ((AccessibleComponent) ac).getForeground();
  1964.                 } else {
  1965.                     Component c = getCurrentComponent();
  1966.                     if (c != null) {
  1967.                         return c.getForeground();
  1968.                     } else {
  1969.                         return null;
  1970.                     }
  1971.                 }
  1972.             }
  1973.  
  1974.             public void setForeground(Color c) {
  1975.                 AccessibleContext ac = getCurrentAccessibleContext();
  1976.                 if (ac instanceof AccessibleComponent) {
  1977.                     ((AccessibleComponent) ac).setForeground(c);
  1978.                 } else {
  1979.                     Component cp = getCurrentComponent();
  1980.                     if (cp != null) {
  1981.                         cp.setForeground(c);
  1982.                     }
  1983.                 }
  1984.             }
  1985.  
  1986.             public Cursor getCursor() {
  1987.                 AccessibleContext ac = getCurrentAccessibleContext();
  1988.                 if (ac instanceof AccessibleComponent) {
  1989.                     return ((AccessibleComponent) ac).getCursor();
  1990.                 } else {
  1991.                     Component c = getCurrentComponent();
  1992.                     if (c != null) {
  1993.                         return c.getCursor();
  1994.                     } else {
  1995.                         Accessible ap = getAccessibleParent();
  1996.                         if (ap instanceof AccessibleComponent) {
  1997.                             return ((AccessibleComponent) ap).getCursor();
  1998.                         } else {
  1999.                             return null;
  2000.                         }
  2001.                     }
  2002.                 }
  2003.             }
  2004.  
  2005.             public void setCursor(Cursor c) {
  2006.                 AccessibleContext ac = getCurrentAccessibleContext();
  2007.                 if (ac instanceof AccessibleComponent) {
  2008.                     ((AccessibleComponent) ac).setCursor(c);
  2009.                 } else {
  2010.                     Component cp = getCurrentComponent();
  2011.                     if (cp != null) {
  2012.                         cp.setCursor(c);
  2013.                     }
  2014.                 }
  2015.             }
  2016.  
  2017.             public Font getFont() {
  2018.                 AccessibleContext ac = getCurrentAccessibleContext();
  2019.                 if (ac instanceof AccessibleComponent) {
  2020.                     return ((AccessibleComponent) ac).getFont();
  2021.                 } else {
  2022.                     Component c = getCurrentComponent();
  2023.                     if (c != null) {
  2024.                         return c.getFont();
  2025.                     } else {
  2026.                         return null;
  2027.                     }
  2028.                 }
  2029.             }
  2030.  
  2031.             public void setFont(Font f) {
  2032.                 AccessibleContext ac = getCurrentAccessibleContext();
  2033.                 if (ac instanceof AccessibleComponent) {
  2034.                     ((AccessibleComponent) ac).setFont(f);
  2035.                 } else {
  2036.                     Component c = getCurrentComponent();
  2037.                     if (c != null) {
  2038.                         c.setFont(f);
  2039.                     }
  2040.                 }
  2041.             }
  2042.  
  2043.             public FontMetrics getFontMetrics(Font f) {
  2044.                 AccessibleContext ac = getCurrentAccessibleContext();
  2045.                 if (ac instanceof AccessibleComponent) {
  2046.                     return ((AccessibleComponent) ac).getFontMetrics(f);
  2047.                 } else {
  2048.                     Component c = getCurrentComponent();
  2049.                     if (c != null) {
  2050.                         return c.getFontMetrics(f);
  2051.                     } else {
  2052.                         return null;
  2053.                     }
  2054.                 }
  2055.             }
  2056.  
  2057.             public boolean isEnabled() {
  2058.                 AccessibleContext ac = getCurrentAccessibleContext();
  2059.                 if (ac instanceof AccessibleComponent) {
  2060.                     return ((AccessibleComponent) ac).isEnabled();
  2061.                 } else {
  2062.                     Component c = getCurrentComponent();
  2063.                     if (c != null) {
  2064.                         return c.isEnabled();
  2065.                     } else {
  2066.                         return false;
  2067.                     }
  2068.                 }
  2069.             }
  2070.  
  2071.             public void setEnabled(boolean b) {
  2072.                 AccessibleContext ac = getCurrentAccessibleContext();
  2073.                 if (ac instanceof AccessibleComponent) {
  2074.                     ((AccessibleComponent) ac).setEnabled(b);
  2075.                 } else {
  2076.                     Component c = getCurrentComponent();
  2077.                     if (c != null) {
  2078.                         c.setEnabled(b);
  2079.                     }
  2080.                 }
  2081.             }
  2082.  
  2083.             public boolean isVisible() {
  2084.             int fi = parent.getFirstVisibleIndex();
  2085.         int li = parent.getLastVisibleIndex();
  2086.                 // The UI incorrectly returns a -1 for the last
  2087.         // visible index if the list is smaller than the
  2088.         // viewport size.
  2089.         if (li == -1) {
  2090.             li = parent.getModel().getSize() - 1;
  2091.         }
  2092.         return ((indexInParent >= fi)
  2093.             && (indexInParent <= li));
  2094.         }
  2095.  
  2096.             public void setVisible(boolean b) {
  2097.             }
  2098.  
  2099.             public boolean isShowing() {
  2100.             return (parent.isShowing() && isVisible());
  2101.             }
  2102.  
  2103.             public boolean contains(Point p) {
  2104.                 AccessibleContext ac = getCurrentAccessibleContext();
  2105.                 if (ac instanceof AccessibleComponent) {
  2106.                     Rectangle r = ((AccessibleComponent) ac).getBounds();
  2107.                     return r.contains(p);
  2108.                 } else {
  2109.                     Component c = getCurrentComponent();
  2110.                     if (c != null) {
  2111.                         Rectangle r = c.getBounds();
  2112.                         return r.contains(p);
  2113.                     } else {
  2114.                         return getBounds().contains(p);
  2115.                     }
  2116.                 }
  2117.             }
  2118.  
  2119.             public Point getLocationOnScreen() {
  2120.                 if (parent != null) {
  2121.                     Point listLocation = parent.getLocationOnScreen();
  2122.                     Point componentLocation = parent.indexToLocation(indexInParent);
  2123.                     componentLocation.translate(listLocation.x, listLocation.y);
  2124.                     return componentLocation;
  2125.                 } else {
  2126.                     return null;
  2127.                 }
  2128.             }
  2129.  
  2130.             public Point getLocation() {
  2131.                 if (parent != null) {
  2132.                     return parent.indexToLocation(indexInParent);
  2133.                 } else {
  2134.                     return null;
  2135.                 }
  2136.             }
  2137.  
  2138.             public void setLocation(Point p) {
  2139.                 if ((parent != null)  && (parent.contains(p))) {
  2140.                     ensureIndexIsVisible(indexInParent);
  2141.                 }
  2142.             }
  2143.  
  2144.             public Rectangle getBounds() {
  2145.                 if (parent != null) {
  2146.                     return parent.getCellBounds(indexInParent,indexInParent);
  2147.                 } else {
  2148.                     return null;
  2149.                 }
  2150.             }
  2151.  
  2152.             public void setBounds(Rectangle r) {
  2153.                 AccessibleContext ac = getCurrentAccessibleContext();
  2154.                 if (ac instanceof AccessibleComponent) {
  2155.                     ((AccessibleComponent) ac).setBounds(r);
  2156.                 }
  2157.             }
  2158.  
  2159.             public Dimension getSize() {
  2160.                 Rectangle cellBounds = this.getBounds();
  2161.                 if (cellBounds != null) {
  2162.                     return cellBounds.getSize();
  2163.                 } else {
  2164.                     return null;
  2165.                 }
  2166.             }
  2167.  
  2168.             public void setSize (Dimension d) {
  2169.                 AccessibleContext ac = getCurrentAccessibleContext();
  2170.                 if (ac instanceof AccessibleComponent) {
  2171.                     ((AccessibleComponent) ac).setSize(d);
  2172.                 } else {
  2173.                     Component c = getCurrentComponent();
  2174.                     if (c != null) {
  2175.                         c.setSize(d);
  2176.                     }
  2177.                 }
  2178.             }
  2179.  
  2180.             public Accessible getAccessibleAt(Point p) {
  2181.                 AccessibleContext ac = getCurrentAccessibleContext();
  2182.                 if (ac instanceof AccessibleComponent) {
  2183.                     return ((AccessibleComponent) ac).getAccessibleAt(p);
  2184.                 } else {
  2185.                     return null;
  2186.                 }
  2187.             }
  2188.  
  2189.             public boolean isFocusTraversable() {
  2190.                 AccessibleContext ac = getCurrentAccessibleContext();
  2191.                 if (ac instanceof AccessibleComponent) {
  2192.                     return ((AccessibleComponent) ac).isFocusTraversable();
  2193.                 } else {
  2194.                     Component c = getCurrentComponent();
  2195.                     if (c != null) {
  2196.                         return c.isFocusTraversable();
  2197.                     } else {
  2198.                         return false;
  2199.                     }
  2200.                 }
  2201.             }
  2202.  
  2203.             public void requestFocus() {
  2204.                 AccessibleContext ac = getCurrentAccessibleContext();
  2205.                 if (ac instanceof AccessibleComponent) {
  2206.                     ((AccessibleComponent) ac).requestFocus();
  2207.                 } else {
  2208.                     Component c = getCurrentComponent();
  2209.                     if (c != null) {
  2210.                         c.requestFocus();
  2211.                     }
  2212.                 }
  2213.             }
  2214.  
  2215.             public void addFocusListener(FocusListener l) {
  2216.                 AccessibleContext ac = getCurrentAccessibleContext();
  2217.                 if (ac instanceof AccessibleComponent) {
  2218.                     ((AccessibleComponent) ac).addFocusListener(l);
  2219.                 } else {
  2220.                     Component c = getCurrentComponent();
  2221.                     if (c != null) {
  2222.                         c.addFocusListener(l);
  2223.                     }
  2224.                 }
  2225.             }
  2226.  
  2227.             public void removeFocusListener(FocusListener l) {
  2228.                 AccessibleContext ac = getCurrentAccessibleContext();
  2229.                 if (ac instanceof AccessibleComponent) {
  2230.                     ((AccessibleComponent) ac).removeFocusListener(l);
  2231.                 } else {
  2232.                     Component c = getCurrentComponent();
  2233.                     if (c != null) {
  2234.                         c.removeFocusListener(l);
  2235.                     }
  2236.                 }
  2237.             }
  2238.         } // inner class AccessibleJListChild
  2239.     } // inner class AccessibleJList
  2240. }
  2241.  
  2242.