KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > JList


1 /*
2  * @(#)JList.java 1.112 04/05/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.swing;
9
10 import java.awt.event.*;
11 import java.awt.*;
12
13 import java.util.Vector JavaDoc;
14 import java.util.Locale JavaDoc;
15
16 import java.beans.*;
17
18 import javax.swing.event.*;
19 import javax.accessibility.*;
20 import javax.swing.plaf.*;
21 import javax.swing.text.Position JavaDoc;
22
23 import java.io.ObjectOutputStream JavaDoc;
24 import java.io.ObjectInputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.Serializable JavaDoc;
27
28
29 /**
30  * A component that allows the user to select one or more objects from a
31  * list. A separate model, <code>ListModel</code>, represents the contents
32  * of the list. It's easy to display an array or vector of objects, using
33  * a <code>JList</code> constructor that builds a <code>ListModel</code>
34  * instance for you:
35  * <pre>
36  * // Create a JList that displays the strings in data[]
37  *
38  * String[] data = {"one", "two", "three", "four"};
39  * JList dataList = new JList(data);
40  *
41  * // The value of the JList model property is an object that provides
42  * // a read-only view of the data. It was constructed automatically.
43  *
44  * for(int i = 0; i < dataList.getModel().getSize(); i++) {
45  * System.out.println(dataList.getModel().getElementAt(i));
46  * }
47  *
48  * // Create a JList that displays the superclass of JList.class.
49  * // We store the superclasses in a java.util.Vector.
50  *
51  * Vector superClasses = new Vector();
52  * Class rootClass = javax.swing.JList.class;
53  * for(Class cls = rootClass; cls != null; cls = cls.getSuperclass()) {
54  * superClasses.addElement(cls);
55  * }
56  * JList classList = new JList(superClasses);
57  * </pre>
58  * <p>
59  * <code>JList</code> doesn't support scrolling directly.
60  * To create a scrolling
61  * list you make the <code>JList</code> the viewport view of a
62  * <code>JScrollPane</code>. For example:
63  * <pre>
64  * JScrollPane scrollPane = new JScrollPane(dataList);
65  * // Or in two steps:
66  * JScrollPane scrollPane = new JScrollPane();
67  * scrollPane.getViewport().setView(dataList);
68  * </pre>
69  * <p>
70  * By default the <code>JList</code> selection model allows any
71  * combination of items to be selected at a time, using the constant
72  * <code>MULTIPLE_INTERVAL_SELECTION</code>.
73  * The selection state is actually managed
74  * by a separate delegate object, an instance of
75  * <code>ListSelectionModel</code>.
76  * However <code>JList</code> provides convenient properties for
77  * managing the selection.
78  * <pre>
79  * String[] data = {"one", "two", "three", "four"};
80  * JList dataList = new JList(data);
81  *
82  * dataList.setSelectedIndex(1); // select "two"
83  * dataList.getSelectedValue(); // returns "two"
84  * </pre>
85  * <p>
86  * The contents of a <code>JList</code> can be dynamic,
87  * in other words, the list elements can
88  * change value and the size of the list can change after the
89  * <code>JList</code> has
90  * been created. The <code>JList</code> observes changes in its model with a
91  * <code>swing.event.ListDataListener</code> implementation. A correct
92  * implementation of <code>ListModel</code> notifies
93  * it's listeners each time a change occurs. The changes are
94  * characterized by a <code>swing.event.ListDataEvent</code>, which identifies
95  * the range of list indices that have been modified, added, or removed.
96  * Simple dynamic-content <code>JList</code> applications can use the
97  * <code>DefaultListModel</code> class to store list elements. This class
98  * implements the <code>ListModel</code> interface and provides the
99  * <code>java.util.Vector</code> API as well. Applications that need to
100  * provide custom <code>ListModel</code> implementations can subclass
101  * <code>AbstractListModel</code>, which provides basic
102  * <code>ListDataListener</code> support. For example:
103  * <pre>
104  * // This list model has about 2^16 elements. Enjoy scrolling.
105  *
106  * <a name="prototype_example">
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 JList(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  * <code>JList</code> uses a <code>java.awt.Component</code>, provided by
124  * a delegate called the
125  * <code>cellRendererer</code>, to paint the visible cells in the list.
126  * The cell renderer component is used like a "rubber stamp" to paint
127  * each visible row. Each time the <code>JList</code> needs to paint a cell
128  * it asks the cell renderer for the component, moves it into place
129  * using <code>setBounds()</code> and then draws it by calling its paint method.
130  * The default cell renderer uses a <code>JLabel</code> component to render
131  * the string value of each component. You can substitute your
132  * own cell renderer, using code like this:
133  * <pre>
134  * // Display an icon and a string for each object in the list.
135  *
136  * <a name="cellrenderer_example">
137  * class MyCellRenderer extends JLabel implements ListCellRenderer {
138  * final static ImageIcon longIcon = new ImageIcon("long.gif");
139  * final static ImageIcon shortIcon = new ImageIcon("short.gif");
140  *
141  * // This is the only method defined by ListCellRenderer.
142  * // We just reconfigure the JLabel each time we're called.
143  *
144  * public Component getListCellRendererComponent(
145  * JList list,
146  * Object value, // value to display
147  * int index, // cell index
148  * boolean isSelected, // is the cell selected
149  * boolean cellHasFocus) // the list and the cell have the focus
150  * {
151  * String s = value.toString();
152  * setText(s);
153  * setIcon((s.length() > 10) ? longIcon : shortIcon);
154  * if (isSelected) {
155  * setBackground(list.getSelectionBackground());
156  * setForeground(list.getSelectionForeground());
157  * }
158  * else {
159  * setBackground(list.getBackground());
160  * setForeground(list.getForeground());
161  * }
162  * setEnabled(list.isEnabled());
163  * setFont(list.getFont());
164  * setOpaque(true);
165  * return this;
166  * }
167  * }
168  *
169  * String[] data = {"one", "two", "three", "four"};
170  * JList dataList = new JList(data);
171  * dataList.setCellRenderer(new MyCellRenderer());
172  * </pre>
173  * <p>
174  * <code>JList</code> doesn't provide any special support for handling double or
175  * triple (or N) mouse clicks however it's easy to handle them using
176  * a <code>MouseListener</code>. Use the <code>JList</code> method
177  * <code>locationToIndex()</code> to
178  * determine what cell was clicked. For example:
179  * <pre>
180  * final JList list = new JList(dataModel);
181  * MouseListener mouseListener = new MouseAdapter() {
182  * public void mouseClicked(MouseEvent e) {
183  * if (e.getClickCount() == 2) {
184  * int index = list.locationToIndex(e.getPoint());
185  * System.out.println("Double clicked on Item " + index);
186  * }
187  * }
188  * };
189  * list.addMouseListener(mouseListener);
190  * </pre>
191  * Note that in this example the <code>dataList</code> is <code>final</code>
192  * because it's referred to by the anonymous <code>MouseListener</code> class.
193  * <p>
194  * <strong>Warning:</strong>
195  * Serialized objects of this class will not be compatible with
196  * future Swing releases. The current serialization support is
197  * appropriate for short term storage or RMI between applications running
198  * the same version of Swing. As of 1.4, support for long term storage
199  * of all JavaBeans<sup><font size="-2">TM</font></sup>
200  * has been added to the <code>java.beans</code> package.
201  * Please see {@link java.beans.XMLEncoder}.
202  *
203  * <p>
204  * See <a HREF="http://java.sun.com/docs/books/tutorial/uiswing/components/list.html">How to Use Lists</a>
205  * in <a HREF="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
206  * for further documentation.
207  * Also see the article <a HREF="http://java.sun.com/products/jfc/tsc/tech_topics/jlist_1/jlist.html">Advanced JList Programming</a>
208  * in <a HREF="http://java.sun.com/products/jfc/tsc"><em>The Swing Connection</em></a>.
209  * <p>
210  * @see ListModel
211  * @see AbstractListModel
212  * @see DefaultListModel
213  * @see ListSelectionModel
214  * @see DefaultListSelectionModel
215  * @see ListCellRenderer
216  *
217  * @beaninfo
218  * attribute: isContainer false
219  * description: A component which allows for the selection of one or more objects from a list.
220  *
221  * @version 1.112 05/05/04
222  * @author Hans Muller
223  */

224 public class JList extends JComponent JavaDoc implements Scrollable JavaDoc, Accessible
225 {
226     /**
227      * @see #getUIClassID
228      * @see #readObject
229      */

230     private static final String JavaDoc uiClassID = "ListUI";
231
232     /**
233      * Indicates the default layout: one column of cells.
234      * @see #setLayoutOrientation
235      * @since 1.4
236      */

237     public static final int VERTICAL = 0;
238
239     /**
240      * Indicates "newspaper style" layout with the cells flowing vertically
241      * then horizontally.
242      * @see #setLayoutOrientation
243      * @since 1.4
244      */

245     public static final int VERTICAL_WRAP = 1;
246
247     /**
248      * Indicates "newspaper style" with the cells flowing horizontally
249      * then vertically.
250      * @see #setLayoutOrientation
251      * @since 1.4
252      */

253     public static final int HORIZONTAL_WRAP = 2;
254
255     private int fixedCellWidth = -1;
256     private int fixedCellHeight = -1;
257     private int horizontalScrollIncrement = -1;
258     private Object JavaDoc prototypeCellValue;
259     private int visibleRowCount = 8;
260     private Color selectionForeground;
261     private Color selectionBackground;
262     private boolean dragEnabled;
263
264     private ListSelectionModel JavaDoc selectionModel;
265     private ListModel JavaDoc dataModel;
266     private ListCellRenderer JavaDoc cellRenderer;
267     private ListSelectionListener selectionListener;
268
269     /**
270      * How to layout the cells, defaults to <code>VERTICAL</code>.
271      */

272     private int layoutOrientation;
273
274     /**
275      * Constructs a <code>JList</code> that displays the elements in the
276      * specified, non-<code>null</code> model.
277      * All <code>JList</code> constructors delegate to this one.
278      *
279      * @param dataModel the data model for this list
280      * @exception IllegalArgumentException if <code>dataModel</code>
281      * is <code>null</code>
282      */

283     public JList(ListModel JavaDoc dataModel)
284     {
285         if (dataModel == null) {
286             throw new IllegalArgumentException JavaDoc("dataModel must be non null");
287         }
288
289         // Register with the ToolTipManager so that tooltips from the
290
// renderer show through.
291
ToolTipManager JavaDoc toolTipManager = ToolTipManager.sharedInstance();
292         toolTipManager.registerComponent(this);
293         
294         layoutOrientation = VERTICAL;
295
296         this.dataModel = dataModel;
297         selectionModel = createSelectionModel();
298         setAutoscrolls(true);
299         setOpaque(true);
300         updateUI();
301     }
302
303
304     /**
305      * Constructs a <code>JList</code> that displays the elements in
306      * the specified array. This constructor just delegates to the
307      * <code>ListModel</code> constructor.
308      *
309      * @param listData the array of Objects to be loaded into the data model
310      */

311     public JList(final Object JavaDoc[] listData)
312     {
313         this (
314             new AbstractListModel JavaDoc() {
315                 public int getSize() { return listData.length; }
316                 public Object JavaDoc getElementAt(int i) { return listData[i]; }
317             }
318         );
319     }
320
321
322     /**
323      * Constructs a <code>JList</code> that displays the elements in
324      * the specified <code>Vector</code>. This constructor just
325      * delegates to the <code>ListModel</code> constructor.
326      *
327      * @param listData the <code>Vector</code> to be loaded into the
328      * data model
329      */

330     public JList(final Vector JavaDoc<?> listData) {
331         this (
332             new AbstractListModel JavaDoc() {
333                 public int getSize() { return listData.size(); }
334                 public Object JavaDoc getElementAt(int i) { return listData.elementAt(i); }
335             }
336         );
337     }
338
339
340     /**
341      * Constructs a <code>JList</code> with an empty model.
342      */

343     public JList() {
344         this (
345             new AbstractListModel JavaDoc() {
346               public int getSize() { return 0; }
347               public Object JavaDoc getElementAt(int i) { return "No Data Model"; }
348             }
349         );
350     }
351
352
353     /**
354      * Returns the look and feel (L&F) object that renders this component.
355      *
356      * @return the <code>ListUI</code> object that renders this component
357      */

358     public ListUI getUI() {
359         return (ListUI)ui;
360     }
361
362
363     /**
364      * Sets the look and feel (L&F) object that renders this component.
365      *
366      * @param ui the <code>ListUI</code> L&F object
367      * @see UIDefaults#getUI
368      * @beaninfo
369      * bound: true
370      * hidden: true
371      * attribute: visualUpdate true
372      * description: The UI object that implements the Component's LookAndFeel.
373      */

374     public void setUI(ListUI ui) {
375         super.setUI(ui);
376     }
377
378
379     /**
380      * Resets the UI property with the value from the current look and feel.
381      *
382      * @see UIManager#getUI
383      */

384     public void updateUI() {
385         setUI((ListUI)UIManager.getUI(this));
386         invalidate();
387     }
388
389
390     /**
391      * Returns the suffix used to construct the name of the look and feel
392      * (L&F) class used to render this component.
393      *
394      * @return the string "ListUI"
395      * @see JComponent#getUIClassID
396      * @see UIDefaults#getUI
397      */

398     public String JavaDoc getUIClassID() {
399         return uiClassID;
400     }
401
402
403     /* -----private-----
404      * This method is called by setPrototypeCellValue and setCellRenderer
405      * to update the fixedCellWidth and fixedCellHeight properties from the
406      * current value of prototypeCellValue (if it's non null).
407      * <p>
408      * This method sets fixedCellWidth and fixedCellHeight but does <b>not</b>
409      * generate PropertyChangeEvents for them.
410      *
411      * @see #setPrototypeCellValue
412      * @see #setCellRenderer
413      */

414     private void updateFixedCellSize()
415     {
416         ListCellRenderer JavaDoc cr = getCellRenderer();
417         Object JavaDoc value = getPrototypeCellValue();
418
419         if ((cr != null) && (value != null)) {
420             Component c = cr.getListCellRendererComponent(this, value, 0, false, false);
421
422             /* The ListUI implementation will add Component c to its private
423              * CellRendererPane however we can't assume that's already
424              * been done here. So we temporarily set the one "inherited"
425              * property that may affect the renderer components preferred size:
426              * its font.
427              */

428             Font f = c.getFont();
429             c.setFont(getFont());
430
431             Dimension d = c.getPreferredSize();
432             fixedCellWidth = d.width;
433             fixedCellHeight = d.height;
434
435             c.setFont(f);
436         }
437     }
438
439
440     /**
441      * Returns the cell width of the "prototypical cell" -- a cell used
442      * for the calculation of cell widths, because it has the same value
443      * as all other list items.
444      *
445      * @return the value of the <code>prototypeCellValue</code> property
446      * @see #setPrototypeCellValue
447      */

448     public Object JavaDoc getPrototypeCellValue() {
449         return prototypeCellValue;
450     }
451
452     /**
453      * Computes the <code>fixedCellWidth</code> and
454      * <code>fixedCellHeight</code> properties
455      * by configuring the <code>cellRenderer</code> to index equals
456      * zero for the specified value and then computing the renderer
457      * component's preferred size. These properties are useful when the
458      * list is too long to allow <code>JList</code> to compute the
459      * width/height of each cell and there is a single cell value that is
460      * known to occupy as much space as any of the others.
461      * <p>
462      * Note that we do set the <code>fixedCellWidth</code> and
463      * <code>fixedCellHeight</code> properties here but only a
464      * <code>prototypeCellValue PropertyChangeEvent</code> is fired.
465      * <p>
466      * To see an example which sets this property,
467      * see the <a href = #prototype_example>class description</a> above.
468      * <p>
469      * The default value of this property is <code>null</code>.
470      * <p>
471      * This is a JavaBeans bound property.
472      *
473      * @param prototypeCellValue the value on which to base
474      * <code>fixedCellWidth</code> and
475      * <code>fixedCellHeight</code>
476      * @see #getPrototypeCellValue
477      * @see #setFixedCellWidth
478      * @see #setFixedCellHeight
479      * @see JComponent#addPropertyChangeListener
480      * @beaninfo
481      * bound: true
482      * attribute: visualUpdate true
483      * description: The cell prototype value, used to compute cell width and height.
484      */

485     public void setPrototypeCellValue(Object JavaDoc prototypeCellValue) {
486         Object JavaDoc oldValue = this.prototypeCellValue;
487         this.prototypeCellValue = prototypeCellValue;
488
489         /* If the cellRenderer has changed and prototypeCellValue
490          * was set, then recompute fixedCellWidth and fixedCellHeight.
491          */

492
493         if ((prototypeCellValue != null) && !prototypeCellValue.equals(oldValue)) {
494             updateFixedCellSize();
495         }
496
497         firePropertyChange("prototypeCellValue", oldValue, prototypeCellValue);
498     }
499
500
501     /**
502      * Returns the fixed cell width value -- the value specified by setting
503      * the <code>fixedCellWidth</code> property, rather than that calculated
504      * from the list elements.
505      *
506      * @return the fixed cell width
507      * @see #setFixedCellWidth
508      */

509     public int getFixedCellWidth() {
510         return fixedCellWidth;
511     }
512
513     /**
514      * Sets the width of every cell in the list. If <code>width</code> is -1,
515      * cell widths are computed by applying <code>getPreferredSize</code>
516      * to the <code>cellRenderer</code> component for each list element.
517      * <p>
518      * The default value of this property is -1.
519      * <p>
520      * This is a JavaBeans bound property.
521      *
522      * @param width the width, in pixels, for all cells in this list
523      * @see #getPrototypeCellValue
524      * @see #setFixedCellWidth
525      * @see JComponent#addPropertyChangeListener
526      * @beaninfo
527      * bound: true
528      * attribute: visualUpdate true
529      * description: Defines a fixed cell width when greater than zero.
530      */

531     public void setFixedCellWidth(int width) {
532         int oldValue = fixedCellWidth;
533         fixedCellWidth = width;
534         firePropertyChange("fixedCellWidth", oldValue, fixedCellWidth);
535     }
536
537
538     /**
539      * Returns the fixed cell height value -- the value specified by setting
540      * the <code>fixedCellHeight</code> property,
541      * rather than that calculated from the list elements.
542      *
543      * @return the fixed cell height, in pixels
544      * @see #setFixedCellHeight
545      */

546     public int getFixedCellHeight() {
547         return fixedCellHeight;
548     }
549
550     /**
551      * Sets the height of every cell in the list. If <code>height</code>
552      * is -1, cell
553      * heights are computed by applying <code>getPreferredSize</code>
554      * to the <code>cellRenderer</code> component for each list element.
555      * <p>
556      * The default value of this property is -1.
557      * <p>
558      * This is a JavaBeans bound property.
559      *
560      * @param height an integer giving the height, in pixels, for all cells
561      * in this list
562      * @see #getPrototypeCellValue
563      * @see #setFixedCellWidth
564      * @see JComponent#addPropertyChangeListener
565      * @beaninfo
566      * bound: true
567      * attribute: visualUpdate true
568      * description: Defines a fixed cell height when greater than zero.
569      */

570     public void setFixedCellHeight(int height) {
571         int oldValue = fixedCellHeight;
572         fixedCellHeight = height;
573         firePropertyChange("fixedCellHeight", oldValue, fixedCellHeight);
574     }
575
576
577     /**
578      * Returns the object that renders the list items.
579      *
580      * @return the <code>ListCellRenderer</code>
581      * @see #setCellRenderer
582      */

583     public ListCellRenderer JavaDoc getCellRenderer() {
584         return cellRenderer;
585     }
586
587     /**
588      * Sets the delegate that's used to paint each cell in the list. If
589      * <code>prototypeCellValue</code> was set then the
590      * <code>fixedCellWidth</code> and <code>fixedCellHeight</code>
591      * properties are set as well. Only one <code>PropertyChangeEvent</code>
592      * is generated however - for the <code>cellRenderer</code> property.
593      * <p>
594      * The default value of this property is provided by the ListUI
595      * delegate, i.e. by the look and feel implementation.
596      * <p>
597      * To see an example which sets the cell renderer,
598      * see the <a href = #cellrenderer_example>class description</a> above.
599      * <p>
600      * This is a JavaBeans bound property.
601      *
602      * @param cellRenderer the <code>ListCellRenderer</code>
603      * that paints list cells
604      * @see #getCellRenderer
605      * @beaninfo
606      * bound: true
607      * attribute: visualUpdate true
608      * description: The component used to draw the cells.
609      */

610     public void setCellRenderer(ListCellRenderer JavaDoc cellRenderer) {
611         ListCellRenderer JavaDoc oldValue = this.cellRenderer;
612         this.cellRenderer = cellRenderer;
613
614         /* If the cellRenderer has changed and prototypeCellValue
615          * was set, then recompute fixedCellWidth and fixedCellHeight.
616          */

617         if ((cellRenderer != null) && !cellRenderer.equals(oldValue)) {
618             updateFixedCellSize();
619         }
620
621         firePropertyChange("cellRenderer", oldValue, cellRenderer);
622     }
623
624
625     /**
626      * Returns the selection foreground color.
627      *
628      * @return the <code>Color</code> object for the foreground property
629      * @see #setSelectionForeground
630      * @see #setSelectionBackground
631      */

632     public Color getSelectionForeground() {
633         return selectionForeground;
634     }
635
636
637     /**
638      * Sets the foreground color for selected cells. Cell renderers
639      * can use this color to render text and graphics for selected
640      * cells.
641      * <p>
642      * The default value of this property is defined by the look
643      * and feel implementation.
644      * <p>
645      * This is a JavaBeans bound property.
646      *
647      * @param selectionForeground the <code>Color</code> to use in the foreground
648      * for selected list items
649      * @see #getSelectionForeground
650      * @see #setSelectionBackground
651      * @see #setForeground
652      * @see #setBackground
653      * @see #setFont
654      * @beaninfo
655      * bound: true
656      * attribute: visualUpdate true
657      * description: The foreground color of selected cells.
658      */

659     public void setSelectionForeground(Color selectionForeground) {
660         Color oldValue = this.selectionForeground;
661         this.selectionForeground = selectionForeground;
662         firePropertyChange("selectionForeground", oldValue, selectionForeground);
663     }
664
665
666     /**
667      * Returns the background color for selected cells.
668      *
669      * @return the <code>Color</code> used for the background of
670      * selected list items
671      * @see #setSelectionBackground
672      * @see #setSelectionForeground
673      */

674     public Color getSelectionBackground() {
675         return selectionBackground;
676     }
677
678
679     /**
680      * Sets the background color for selected cells. Cell renderers
681      * can use this color to the fill selected cells.
682      * <p>
683      * The default value of this property is defined by the look
684      * and feel implementation.
685      * <p>
686      * This is a JavaBeans bound property.
687      *
688      * @param selectionBackground the <code>Color</code> to use for the
689      * background of selected cells
690      * @see #getSelectionBackground
691      * @see #setSelectionForeground
692      * @see #setForeground
693      * @see #setBackground
694      * @see #setFont
695      * @beaninfo
696      * bound: true
697      * attribute: visualUpdate true
698      * description: The background color of selected cells.
699      */

700     public void setSelectionBackground(Color selectionBackground) {
701         Color oldValue = this.selectionBackground;
702         this.selectionBackground = selectionBackground;
703         firePropertyChange("selectionBackground", oldValue, selectionBackground);
704     }
705
706
707     /**
708      * Returns the preferred number of visible rows.
709      *
710      * @return an integer indicating the preferred number of rows to display
711      * without using a scroll bar
712      * @see #setVisibleRowCount
713      */

714     public int getVisibleRowCount() {
715         return visibleRowCount;
716     }
717
718     /**
719      * Sets the preferred number of rows in the list that can be displayed
720      * without a scrollbar, as determined by the nearest
721      * <code>JViewport</code> ancestor, if any.
722      * The value of this property only affects the value of
723      * the <code>JList</code>'s <code>preferredScrollableViewportSize</code>.
724      * <p>
725      * The default value of this property is 8.
726      * <p>
727      * This is a JavaBeans bound property.
728      *
729      * @param visibleRowCount an integer specifying the preferred number of
730      * visible rows
731      * @see #getVisibleRowCount
732      * @see JComponent#getVisibleRect
733      * @see JViewport
734      * @beaninfo
735      * bound: true
736      * attribute: visualUpdate true
737      * description: The preferred number of cells that can be displayed without a scroll bar.
738      */

739     public void setVisibleRowCount(int visibleRowCount) {
740         int oldValue = this.visibleRowCount;
741         this.visibleRowCount = Math.max(0, visibleRowCount);
742         firePropertyChange("visibleRowCount", oldValue, visibleRowCount);
743     }
744
745
746     /**
747      * Returns <code>JList.VERTICAL</code> if the layout is a single
748      * column of cells, or <code>JList.VERTICAL_WRAP</code> if the layout
749      * is "newspaper style" with the content flowing vertically then
750      * horizontally or <code>JList.HORIZONTAL_WRAP</code> if the layout is
751      * "newspaper style" with the content flowing horizontally then
752      * vertically.
753      *
754      * @return the value of the layoutOrientation property
755      * @see #setLayoutOrientation
756      * @since 1.4
757      */

758     public int getLayoutOrientation() {
759     return layoutOrientation;
760     }
761
762
763     /**
764      * Defines the way list cells are layed out. Consider a <code>JList</code>
765      * with four cells, this can be layed out in one of the following ways:
766      * <pre>
767      * 0
768      * 1
769      * 2
770      * 3
771      * </pre>
772      * <pre>
773      * 0 1
774      * 2 3
775      * </pre>
776      * <pre>
777      * 0 2
778      * 1 3
779      * </pre>
780      * <p>
781      * These correspond to the following values:
782      *
783      * <table border="1"
784      * summary="Describes layouts VERTICAL, HORIZONTAL_WRAP, and VERTICAL_WRAP">
785      * <tr><th><p align="left">Value</p></th><th><p align="left">Description</p></th></tr>
786      * <tr><td><code>JList.VERTICAL</code>
787      * <td>The cells should be layed out vertically in one column.
788      * <tr><td><code>JList.HORIZONTAL_WRAP</code>
789      * <td>The cells should be layed out horizontally, wrapping to
790      * a new row as necessary. The number
791      * of rows to use will either be defined by
792      * <code>getVisibleRowCount</code> if > 0, otherwise the
793      * number of rows will be determined by the width of the
794      * <code>JList</code>.
795      * <tr><td><code>JList.VERTICAL_WRAP</code>
796      * <td>The cells should be layed out vertically, wrapping to a
797      * new column as necessary. The number
798      * of rows to use will either be defined by
799      * <code>getVisibleRowCount</code> if > 0, otherwise the
800      * number of rows will be determined by the height of the
801      * <code>JList</code>.
802      * </table>
803      * The default value of this property is <code>JList.VERTICAL</code>.
804      * <p>
805      * This will throw an <code>IllegalArgumentException</code> if
806      * <code>layoutOrientation</code> is not one of
807      * <code>JList.HORIZONTAL_WRAP</code> or <code>JList.VERTICAL</code> or
808      * <code>JList.VERTICAL_WRAP</code>
809      *
810      * @param layoutOrientation New orientation, one of
811      * <code>JList.HORIZONTAL_WRAP</code>, <code>JList.VERTICAL</code>
812      * or <code>JList.VERTICAL_WRAP</code>.
813      * @see #getLayoutOrientation
814      * @see #setVisibleRowCount
815      * @see #getScrollableTracksViewportHeight
816      * @since 1.4
817      * @beaninfo
818      * bound: true
819      * attribute: visualUpdate true
820      * description: Defines the way list cells are layed out.
821      * enum: VERTICAL JList.VERTICAL
822      * HORIZONTAL_WRAP JList.HORIZONTAL_WRAP
823      * VERTICAL_WRAP JList.VERTICAL_WRAP
824      */

825     public void setLayoutOrientation(int layoutOrientation) {
826     int oldValue = this.layoutOrientation;
827     switch (layoutOrientation) {
828     case VERTICAL:
829     case VERTICAL_WRAP:
830         case HORIZONTAL_WRAP:
831         this.layoutOrientation = layoutOrientation;
832         firePropertyChange("layoutOrientation", oldValue, layoutOrientation);
833         break;
834     default:
835             throw new IllegalArgumentException JavaDoc("layoutOrientation must be one of: VERTICAL, HORIZONTAL_WRAP or VERTICAL_WRAP");
836     }
837     }
838
839
840     /**
841      * Returns the index of the first visible cell. The cell considered
842      * to be "first" depends on the list's <code>componentOrientation</code>
843      * property. If the orientation is horizontal left-to-right, then
844      * the first visible cell is in the list's upper-left corner. If
845      * the orientation is horizontal right-to-left, then the first
846      * visible cell is in the list's upper-right corner. If nothing is
847      * visible or the list is empty, a -1 is returned. Note that the returned
848      * cell may only be partially visible.
849      *
850      * @return the index of the first visible cell
851      * @see #getLastVisibleIndex
852      * @see JComponent#getVisibleRect
853      */

854     public int getFirstVisibleIndex() {
855     Rectangle r = getVisibleRect();
856         int first;
857         if (this.getComponentOrientation().isLeftToRight()) {
858             first = locationToIndex(r.getLocation());
859         } else {
860             first = locationToIndex(new Point((r.x + r.width) - 1, r.y));
861         }
862     if (first != -1) {
863         Rectangle bounds = getCellBounds(first, first);
864         if (bounds != null) {
865                 SwingUtilities.computeIntersection(r.x, r.y, r.width, r.height, bounds);
866                 if (bounds.width == 0 || bounds.height == 0) {
867             first = -1;
868         }
869         }
870     }
871     return first;
872     }
873
874
875     /**
876      * Returns the index of the last visible cell. The cell considered
877      * to be "last" depends on the list's <code>componentOrientation</code>
878      * property. If the orientation is horizontal left-to-right, then
879      * the last visible cell is in the JList's lower-right corner. If
880      * the orientation is horizontal right-to-left, then the last visible
881      * cell is in the JList's lower-left corner. If nothing is visible
882      * or the list is empty, a -1 is returned. Note that the returned
883      * cell may only be partially visible.
884      *
885      * @return the index of the last visible cell
886      * @see #getFirstVisibleIndex
887      * @see JComponent#getVisibleRect
888      */

889     public int getLastVisibleIndex() {
890         boolean leftToRight = this.getComponentOrientation().isLeftToRight();
891         Rectangle r = getVisibleRect();
892         Point lastPoint;
893         if (leftToRight) {
894             lastPoint = new Point((r.x + r.width) - 1, (r.y + r.height) - 1);
895         } else {
896             lastPoint = new Point(r.x, (r.y + r.height) - 1);
897         }
898         int location = locationToIndex(lastPoint);
899
900         if (location != -1) {
901             Rectangle bounds = getCellBounds(location, location);
902
903             if (bounds != null) {
904                 SwingUtilities.computeIntersection(r.x, r.y, r.width, r.height, bounds);
905                 if (bounds.width == 0 || bounds.height == 0) {
906             // Try the lower left corner, and then go across checking
907
// each cell.
908
Point visibleLL = new Point(r.x, lastPoint.y);
909             int last;
910             int llIndex = -1;
911             int lrIndex = location;
912             location = -1;
913
914             do {
915             last = llIndex;
916             llIndex = locationToIndex(visibleLL);
917
918             if (llIndex != -1) {
919                 bounds = getCellBounds(llIndex, llIndex);
920                 if (llIndex != lrIndex && bounds != null &&
921                 bounds.contains(visibleLL)) {
922                 location = llIndex;
923                 visibleLL.x = bounds.x + bounds.width + 1;
924                 if (visibleLL.x >= lastPoint.x) {
925                                 // Past visible region, bail.
926
last = llIndex;
927                 }
928                 }
929                 else {
930                 last = llIndex;
931                 }
932             }
933             } while (llIndex != -1 && last != llIndex);
934         }
935             }
936         }
937         return location;
938     }
939
940
941     /**
942      * Scrolls the viewport to make the specified cell completely visible.
943      * Note, for this method to work, the <code>JList</code> must be
944      * displayed within a <code>JViewport</code>.
945      *
946      * @param index the index of the cell to make visible
947      * @see JComponent#scrollRectToVisible
948      * @see #getVisibleRect
949      */

950     public void ensureIndexIsVisible(int index) {
951         Rectangle cellBounds = getCellBounds(index, index);
952         if (cellBounds != null) {
953             scrollRectToVisible(cellBounds);
954         }
955     }
956
957     /**
958      * Sets the <code>dragEnabled</code> property,
959      * which must be <code>true</code> to enable
960      * automatic drag handling (the first part of drag and drop)
961      * on this component.
962      * The <code>transferHandler</code> property needs to be set
963      * to a non-<code>null</code> value for the drag to do
964      * anything. The default value of the <code>dragEnabled</code>
965      * property
966      * is <code>false</code>.
967      *
968      * <p>
969      *
970      * When automatic drag handling is enabled,
971      * most look and feels begin a drag-and-drop operation
972      * whenever the user presses the mouse button over a selection
973      * and then moves the mouse a few pixels.
974      * Setting this property to <code>true</code>
975      * can therefore have a subtle effect on
976      * how selections behave.
977      *
978      * <p>
979      *
980      * Some look and feels might not support automatic drag and drop;
981      * they will ignore this property. You can work around such
982      * look and feels by modifying the component
983      * to directly call the <code>exportAsDrag</code> method of a
984      * <code>TransferHandler</code>.
985      *
986      * @param b the value to set the <code>dragEnabled</code> property to
987      * @exception HeadlessException if
988      * <code>b</code> is <code>true</code> and
989      * <code>GraphicsEnvironment.isHeadless()</code>
990      * returns <code>true</code>
991      * @see java.awt.GraphicsEnvironment#isHeadless
992      * @see #getDragEnabled
993      * @see #setTransferHandler
994      * @see TransferHandler
995      * @since 1.4
996      *
997      * @beaninfo
998      * description: determines whether automatic drag handling is enabled
999      * bound: false
1000     */

1001    public void setDragEnabled(boolean b) {
1002        if (b && GraphicsEnvironment.isHeadless()) {
1003            throw new HeadlessException();
1004        }
1005    dragEnabled = b;
1006    }
1007
1008    /**
1009     * Gets the <code>dragEnabled</code> property.
1010     *
1011     * @return the value of the <code>dragEnabled</code> property
1012     * @see #setDragEnabled
1013     * @since 1.4
1014     */

1015    public boolean getDragEnabled() {
1016    return dragEnabled;
1017    }
1018
1019    /**
1020     * Returns the next list element that starts with
1021     * a prefix.
1022     *
1023     * @param prefix the string to test for a match
1024     * @param startIndex the index for starting the search
1025     * @param bias the search direction, either
1026     * Position.Bias.Forward or Position.Bias.Backward.
1027     * @return the index of the next list element that
1028     * starts with the prefix; otherwise -1
1029     * @exception IllegalArgumentException if prefix is null
1030     * or startIndex is out of bounds
1031     * @since 1.4
1032     */

1033    public int getNextMatch(String JavaDoc prefix, int startIndex, Position.Bias JavaDoc bias) {
1034    ListModel JavaDoc model = getModel();
1035    int max = model.getSize();
1036    if (prefix == null) {
1037        throw new IllegalArgumentException JavaDoc();
1038    }
1039    if (startIndex < 0 || startIndex >= max) {
1040        throw new IllegalArgumentException JavaDoc();
1041    }
1042    prefix = prefix.toUpperCase();
1043
1044    // start search from the next element after the selected element
1045
int increment = (bias == Position.Bias.Forward) ? 1 : -1;
1046    int index = startIndex;
1047    do {
1048        Object JavaDoc o = model.getElementAt(index);
1049        
1050        if (o != null) {
1051        String JavaDoc string;
1052        
1053        if (o instanceof String JavaDoc) {
1054            string = ((String JavaDoc)o).toUpperCase();
1055        }
1056        else {
1057            string = o.toString();
1058            if (string != null) {
1059            string = string.toUpperCase();
1060            }
1061        }
1062        
1063        if (string != null && string.startsWith(prefix)) {
1064            return index;
1065        }
1066        }
1067        index = (index + increment + max) % max;
1068    } while (index != startIndex);
1069    return -1;
1070    }
1071
1072    /**
1073     * Overrides <code>JComponent</code>'s <code>getToolTipText</code>
1074     * method in order to allow the renderer's tips to be used
1075     * if it has text set.
1076     * <p>
1077     * <bold>Note:</bold> For <code>JList</code> to properly display
1078     * tooltips of its renderers
1079     * <code>JList</code> must be a registered component with the
1080     * <code>ToolTipManager</code>.
1081     * This is done automatically in the constructor,
1082     * but if at a later point <code>JList</code> is told
1083     * <code>setToolTipText(null)</code> it will unregister the list
1084     * component, and no tips from renderers will display anymore.
1085     *
1086     * @see JComponent#getToolTipText
1087     */

1088    public String JavaDoc getToolTipText(MouseEvent event) {
1089        if(event != null) {
1090            Point p = event.getPoint();
1091            int index = locationToIndex(p);
1092            ListCellRenderer JavaDoc r = getCellRenderer();
1093            Rectangle cellBounds;
1094
1095            if (index != -1 && r != null && (cellBounds =
1096                               getCellBounds(index, index)) != null &&
1097                               cellBounds.contains(p.x, p.y)) {
1098                ListSelectionModel JavaDoc lsm = getSelectionModel();
1099                Component rComponent = r.getListCellRendererComponent(
1100                           this, getModel().getElementAt(index), index,
1101                           lsm.isSelectedIndex(index),
1102                           (hasFocus() && (lsm.getLeadSelectionIndex() ==
1103                                           index)));
1104
1105                if(rComponent instanceof JComponent JavaDoc) {
1106                    MouseEvent newEvent;
1107
1108                    p.translate(-cellBounds.x, -cellBounds.y);
1109                    newEvent = new MouseEvent(rComponent, event.getID(),
1110                                              event.getWhen(),
1111                                              event.getModifiers(),
1112                                              p.x, p.y, event.getClickCount(),
1113                                              event.isPopupTrigger());
1114
1115                    String JavaDoc tip = ((JComponent JavaDoc)rComponent).getToolTipText(
1116                                              newEvent);
1117
1118                    if (tip != null) {
1119                        return tip;
1120                    }
1121                }
1122            }
1123        }
1124        return super.getToolTipText();
1125    }
1126
1127    /**
1128     * --- ListUI Delegations ---
1129     */

1130
1131
1132    /**
1133     * Convert a point in <code>JList</code> coordinates to the closest index
1134     * of the cell at that location. To determine if the cell actually
1135     * contains the specified location use a combination of this method and
1136     * <code>getCellBounds</code>. Returns -1 if the model is empty.
1137     *
1138     * @param location the coordinates of the cell, relative to
1139     * <code>JList</code>
1140     * @return an integer -- the index of the cell at the given location, or -1.
1141     */

1142    public int locationToIndex(Point location) {
1143        ListUI ui = getUI();
1144        return (ui != null) ? ui.locationToIndex(this, location) : -1;
1145    }
1146
1147
1148    /**
1149     * Returns the origin of the specified item in <code>JList</code>
1150     * coordinates. Returns <code>null</code> if <code>index</code> isn't valid.
1151     *
1152     * @param index the index of the <code>JList</code> cell
1153     * @return the origin of the index'th cell
1154     */

1155    public Point indexToLocation(int index) {
1156        ListUI ui = getUI();
1157        return (ui != null) ? ui.indexToLocation(this, index) : null;
1158    }
1159
1160
1161    /**
1162     * Returns the bounds of the specified range of items in <code>JList</code>
1163     * coordinates. Returns <code>null</code> if index isn't valid.
1164     *
1165     * @param index0 the index of the first <code>JList</code> cell in the range
1166     * @param index1 the index of the last <code>JList</code> cell in the range
1167     * @return the bounds of the indexed cells in pixels
1168     */

1169    public Rectangle getCellBounds(int index0, int index1) {
1170        ListUI ui = getUI();
1171        return (ui != null) ? ui.getCellBounds(this, index0, index1) : null;
1172    }
1173
1174
1175    /**
1176     * --- ListModel Support ---
1177     */

1178
1179
1180    /**
1181     * Returns the data model that holds the list of items displayed
1182     * by the <code>JList</code> component.
1183     *
1184     * @return the <code>ListModel</code> that provides the displayed
1185     * list of items
1186     * @see #setModel
1187     */

1188    public ListModel JavaDoc getModel() {
1189        return dataModel;
1190    }
1191
1192    /**
1193     * Sets the model that represents the contents or "value" of the
1194     * list and clears the list selection after notifying
1195     * <code>PropertyChangeListeners</code>.
1196     * <p>
1197     * This is a JavaBeans bound property.
1198     *
1199     * @param model the <code>ListModel</code> that provides the
1200     * list of items for display
1201     * @exception IllegalArgumentException if <code>model</code> is
1202     * <code>null</code>
1203     * @see #getModel
1204     * @beaninfo
1205     * bound: true
1206     * attribute: visualUpdate true
1207     * description: The object that contains the data to be drawn by this JList.
1208     */

1209    public void setModel(ListModel JavaDoc model) {
1210        if (model == null) {
1211            throw new IllegalArgumentException JavaDoc("model must be non null");
1212        }
1213        ListModel JavaDoc oldValue = dataModel;
1214        dataModel = model;
1215        firePropertyChange("model", oldValue, dataModel);
1216        clearSelection();
1217    }
1218
1219
1220    /**
1221     * Constructs a <code>ListModel</code> from an array of objects and then
1222     * applies <code>setModel</code> to it.
1223     *
1224     * @param listData an array of Objects containing the items to display
1225     * in the list
1226     * @see #setModel
1227     */

1228    public void setListData(final Object JavaDoc[] listData) {
1229        setModel (
1230            new AbstractListModel JavaDoc() {
1231                public int getSize() { return listData.length; }
1232                public Object JavaDoc getElementAt(int i) { return listData[i]; }
1233            }
1234        );
1235    }
1236
1237
1238    /**
1239     * Constructs a <code>ListModel</code> from a <code>Vector</code> and then
1240     * applies <code>setModel</code> to it.
1241     *
1242     * @param listData a <code>Vector</code> containing the items to
1243     * display in the list
1244     * @see #setModel
1245     */

1246    public void setListData(final Vector JavaDoc<?> listData) {
1247        setModel (
1248            new AbstractListModel JavaDoc() {
1249                public int getSize() { return listData.size(); }
1250                public Object JavaDoc getElementAt(int i) { return listData.elementAt(i); }
1251            }
1252        );
1253    }
1254
1255
1256    /**
1257     * --- ListSelectionModel delegations and extensions ---
1258     */

1259
1260
1261    /**
1262     * Returns an instance of <code>DefaultListSelectionModel</code>. This
1263     * method is used by the constructor to initialize the
1264     * <code>selectionModel</code> property.
1265     *
1266     * @return the <code>ListSelectionModel</code> used by this
1267     * <code>JList</code>.
1268     * @see #setSelectionModel
1269     * @see DefaultListSelectionModel
1270     */

1271    protected ListSelectionModel JavaDoc createSelectionModel() {
1272        return new DefaultListSelectionModel JavaDoc();
1273    }
1274
1275
1276    /**
1277     * Returns the value of the current selection model. The selection
1278     * model handles the task of making single selections, selections
1279     * of contiguous ranges, and non-contiguous selections.
1280     *
1281     * @return the <code>ListSelectionModel</code> that implements
1282     * list selections
1283     * @see #setSelectionModel
1284     * @see ListSelectionModel
1285     */

1286    public ListSelectionModel JavaDoc getSelectionModel() {
1287        return selectionModel;
1288    }
1289
1290
1291    /**
1292     * Notifies <code>JList</code> <code>ListSelectionListener</code>s that
1293     * the selection model has changed. It's used to forward
1294     * <code>ListSelectionEvents</code> from the <code>selectionModel</code>
1295     * to the <code>ListSelectionListener</code>s added directly to the
1296     * <code>JList</code>.
1297     * @param firstIndex the first selected index
1298     * @param lastIndex the last selected index
1299     * @param isAdjusting true if multiple changes are being made
1300     *
1301     * @see #addListSelectionListener
1302     * @see #removeListSelectionListener
1303     * @see EventListenerList
1304     */

1305    protected void fireSelectionValueChanged(int firstIndex, int lastIndex,
1306                                             boolean isAdjusting)
1307    {
1308        Object JavaDoc[] listeners = listenerList.getListenerList();
1309        ListSelectionEvent e = null;
1310
1311        for (int i = listeners.length - 2; i >= 0; i -= 2) {
1312            if (listeners[i] == ListSelectionListener.class) {
1313                if (e == null) {
1314                    e = new ListSelectionEvent(this, firstIndex, lastIndex,
1315                                               isAdjusting);
1316                }
1317                ((ListSelectionListener)listeners[i+1]).valueChanged(e);
1318            }
1319        }
1320    }
1321
1322
1323    /* A ListSelectionListener that forwards ListSelectionEvents from
1324     * the selectionModel to the JList ListSelectionListeners. The
1325     * forwarded events only differ from the originals in that their
1326     * source is the JList instead of the selectionModel itself.
1327     */

1328    private class ListSelectionHandler implements ListSelectionListener, Serializable JavaDoc
1329    {
1330    public void valueChanged(ListSelectionEvent e) {
1331        fireSelectionValueChanged(e.getFirstIndex(),
1332                      e.getLastIndex(),
1333                      e.getValueIsAdjusting());
1334    }
1335    }
1336    
1337
1338    /**
1339     * Adds a listener to the list that's notified each time a change
1340     * to the selection occurs. Listeners added directly to the
1341     * <code>JList</code>
1342     * will have their <code>ListSelectionEvent.getSource() ==
1343     * this JList</code>
1344     * (instead of the <code>ListSelectionModel</code>).
1345     *
1346     * @param listener the <code>ListSelectionListener</code> to add
1347     * @see #getSelectionModel
1348     * @see #getListSelectionListeners
1349     */

1350    public void addListSelectionListener(ListSelectionListener listener)
1351    {
1352        if (selectionListener == null) {
1353            selectionListener = new ListSelectionHandler();
1354            getSelectionModel().addListSelectionListener(selectionListener);
1355        }
1356
1357        listenerList.add(ListSelectionListener.class, listener);
1358    }
1359
1360
1361    /**
1362     * Removes a listener from the list that's notified each time a
1363     * change to the selection occurs.
1364     *
1365     * @param listener the <code>ListSelectionListener</code> to remove
1366     * @see #addListSelectionListener
1367     * @see #getSelectionModel
1368     */

1369    public void removeListSelectionListener(ListSelectionListener listener) {
1370        listenerList.remove(ListSelectionListener.class, listener);
1371    }
1372
1373
1374    /**
1375     * Returns an array of all the <code>ListSelectionListener</code>s added
1376     * to this JList with addListSelectionListener().
1377     *
1378     * @return all of the <code>ListSelectionListener</code>s added or an empty
1379     * array if no listeners have been added
1380     * @see #addListSelectionListener
1381     * @since 1.4
1382     */

1383    public ListSelectionListener[] getListSelectionListeners() {
1384        return (ListSelectionListener[])listenerList.getListeners(
1385                ListSelectionListener.class);
1386    }
1387
1388
1389    /**
1390     * Sets the <code>selectionModel</code> for the list to a
1391     * non-<code>null</code> <code>ListSelectionModel</code>
1392     * implementation. The selection model handles the task of making single
1393     * selections, selections of contiguous ranges, and non-contiguous
1394     * selections.
1395     * <p>
1396     * This is a JavaBeans bound property.
1397     *
1398     * @param selectionModel the <code>ListSelectionModel</code> that
1399     * implements the selections
1400     * @exception IllegalArgumentException if <code>selectionModel</code>
1401     * is <code>null</code>
1402     * @see #getSelectionModel
1403     * @beaninfo
1404     * bound: true
1405     * description: The selection model, recording which cells are selected.
1406     */

1407    public void setSelectionModel(ListSelectionModel JavaDoc selectionModel) {
1408        if (selectionModel == null) {
1409            throw new IllegalArgumentException JavaDoc("selectionModel must be non null");
1410        }
1411
1412        /* Remove the forwarding ListSelectionListener from the old
1413         * selectionModel, and add it to the new one, if necessary.
1414         */

1415        if (selectionListener != null) {
1416            this.selectionModel.removeListSelectionListener(selectionListener);
1417            selectionModel.addListSelectionListener(selectionListener);
1418        }
1419
1420        ListSelectionModel JavaDoc oldValue = this.selectionModel;
1421        this.selectionModel = selectionModel;
1422        firePropertyChange("selectionModel", oldValue, selectionModel);
1423    }
1424
1425
1426    /**
1427     * Determines whether single-item or multiple-item
1428     * selections are allowed.
1429     * The following <code>selectionMode</code> values are allowed:
1430     * <ul>
1431     * <li> <code>ListSelectionModel.SINGLE_SELECTION</code>
1432     * Only one list index can be selected at a time. In this
1433     * mode the <code>setSelectionInterval</code> and
1434     * <code>addSelectionInterval</code>
1435     * methods are equivalent, and only the second index
1436     * argument is used.
1437     * <li> <code>ListSelectionModel.SINGLE_INTERVAL_SELECTION</code>
1438     * One contiguous index interval can be selected at a time.
1439     * In this mode <code>setSelectionInterval</code> and
1440     * <code>addSelectionInterval</code>
1441     * are equivalent.
1442     * <li> <code>ListSelectionModel.MULTIPLE_INTERVAL_SELECTION</code>
1443     * In this mode, there's no restriction on what can be selected.
1444     * This is the default.
1445     * </ul>
1446     *
1447     * @param selectionMode an integer specifying the type of selections
1448     * that are permissible
1449     * @see #getSelectionMode
1450     * @beaninfo
1451     * description: The selection mode.
1452     * enum: SINGLE_SELECTION ListSelectionModel.SINGLE_SELECTION
1453     * SINGLE_INTERVAL_SELECTION ListSelectionModel.SINGLE_INTERVAL_SELECTION
1454     * MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
1455     */

1456    public void setSelectionMode(int selectionMode) {
1457        getSelectionModel().setSelectionMode(selectionMode);
1458    }
1459
1460    /**
1461     * Returns whether single-item or multiple-item selections are allowed.
1462     *
1463     * @return the value of the <code>selectionMode</code> property
1464     * @see #setSelectionMode
1465     */

1466    public int getSelectionMode() {
1467        return getSelectionModel().getSelectionMode();
1468    }
1469
1470
1471    /**
1472     * Returns the first index argument from the most recent
1473     * <code>addSelectionModel</code> or <code>setSelectionInterval</code> call.
1474     * This is a convenience method that just delegates to the
1475     * <code>selectionModel</code>.
1476     *
1477     * @return the index that most recently anchored an interval selection
1478     * @see ListSelectionModel#getAnchorSelectionIndex
1479     * @see #addSelectionInterval
1480     * @see #setSelectionInterval
1481     * @see #addListSelectionListener
1482     */

1483    public int getAnchorSelectionIndex() {
1484        return getSelectionModel().getAnchorSelectionIndex();
1485    }
1486
1487
1488    /**
1489     * Returns the second index argument from the most recent
1490     * <code>addSelectionInterval</code> or <code>setSelectionInterval</code>
1491     * call.
1492     * This is a convenience method that just delegates to the
1493     * <code>selectionModel</code>.
1494     *
1495     * @return the index that most recently ended a interval selection
1496     * @see ListSelectionModel#getLeadSelectionIndex
1497     * @see #addSelectionInterval
1498     * @see #setSelectionInterval
1499     * @see #addListSelectionListener
1500     * @beaninfo
1501     * description: The lead selection index.
1502     */

1503    public int getLeadSelectionIndex() {
1504        return getSelectionModel().getLeadSelectionIndex();
1505    }
1506
1507
1508    /**
1509     * Returns the smallest selected cell index.
1510     * This is a convenience method that just delegates to the
1511     * <code>selectionModel</code>.
1512     *
1513     * @return the smallest selected cell index
1514     * @see ListSelectionModel#getMinSelectionIndex
1515     * @see #addListSelectionListener
1516     */

1517    public int getMinSelectionIndex() {
1518        return getSelectionModel().getMinSelectionIndex();
1519    }
1520
1521
1522    /**
1523     * Returns the largest selected cell index.
1524     * This is a convenience method that just delegates to the
1525     * <code>selectionModel</code>.
1526     *
1527     * @return the largest selected cell index
1528     * @see ListSelectionModel#getMaxSelectionIndex
1529     * @see #addListSelectionListener
1530     */

1531    public int getMaxSelectionIndex() {
1532        return getSelectionModel().getMaxSelectionIndex();
1533    }
1534
1535
1536    /**
1537     * Returns true if the specified index is selected.
1538     * This is a convenience method that just delegates to the
1539     * <code>selectionModel</code>.
1540     *
1541     * @param index index to be queried for selection state
1542     * @return true if the specified index is selected
1543     * @see ListSelectionModel#isSelectedIndex
1544     * @see #setSelectedIndex
1545     * @see #addListSelectionListener
1546     */

1547    public boolean isSelectedIndex(int index) {
1548        return getSelectionModel().isSelectedIndex(index);
1549    }
1550
1551
1552    /**
1553     * Returns true if nothing is selected.
1554     * This is a convenience method that just delegates to the
1555     * <code>selectionModel</code>.
1556     *
1557     * @return true if nothing is selected
1558     * @see ListSelectionModel#isSelectionEmpty
1559     * @see #clearSelection
1560     * @see #addListSelectionListener
1561     */

1562    public boolean isSelectionEmpty() {
1563        return getSelectionModel().isSelectionEmpty();
1564    }
1565
1566
1567    /**
1568     * Clears the selection - after calling this method
1569     * <code>isSelectionEmpty</code> will return true.
1570     * This is a convenience method that just delegates to the
1571     * <code>selectionModel</code>.
1572     *
1573     * @see ListSelectionModel#clearSelection
1574     * @see #isSelectionEmpty
1575     * @see #addListSelectionListener
1576     */

1577    public void clearSelection() {
1578        getSelectionModel().clearSelection();
1579    }
1580
1581
1582    /**
1583     * Selects the specified interval. Both the <code>anchor</code>
1584     * and <code>lead</code> indices are included. It's not
1585     * necessary for <code>anchor</code> to be less than <code>lead</code>.
1586     * This is a convenience method that just delegates to the
1587     * <code>selectionModel</code>.
1588     * The <code>DefaultListSelectionModel</code> implementation
1589     * will do nothing if either <code>anchor</code> or
1590     * <code>lead</code> are -1.
1591     * If <code>anchor</code> or <code>lead</code> are less than -1,
1592     * <code>IndexOutOfBoundsException</code> is thrown.
1593     *
1594     * @param anchor the first index to select
1595     * @param lead the last index to select
1596     * @exception IndexOutOfBoundsException if either <code>anchor</code>
1597     * or <code>lead</code> are less than -1
1598     * @see ListSelectionModel#setSelectionInterval
1599     * @see #addSelectionInterval
1600     * @see #removeSelectionInterval
1601     * @see #addListSelectionListener
1602     */

1603    public void setSelectionInterval(int anchor, int lead) {
1604        getSelectionModel().setSelectionInterval(anchor, lead);
1605    }
1606
1607
1608    /**
1609     * Sets the selection to be the union of the specified interval with current
1610     * selection. Both the anchor and lead indices are
1611     * included. It's not necessary for anchor to be less than lead.
1612     * This is a convenience method that just delegates to the
1613     * <code>selectionModel</code>. The
1614     * <code>DefaultListSelectionModel</code> implementation
1615     * will do nothing if either <code>anchor</code> or
1616     * <code>lead</code> are -1.
1617     * If <code>anchor</code> or <code>lead</code> are less than -1,
1618     * <code>IndexOutOfBoundsException</code> is thrown.
1619     *
1620     * @param anchor the first index to add to the selection
1621     * @param lead the last index to add to the selection
1622     * @see ListSelectionModel#addSelectionInterval
1623     * @see #setSelectionInterval
1624     * @see #removeSelectionInterval
1625     * @see #addListSelectionListener
1626     * @exception IndexOutOfBoundsException if either <code>anchor</code>
1627     * or <code>lead</code> are less than -1
1628     */

1629    public void addSelectionInterval(int anchor, int lead) {
1630        getSelectionModel().addSelectionInterval(anchor, lead);
1631    }
1632
1633
1634    /**
1635     * Sets the selection to be the set difference of the specified interval
1636     * and the current selection. Both the <code>index0</code> and
1637     * <code>index1</code> indices are removed. It's not necessary for
1638     * <code>index0</code> to be less than <code>index1</code>.
1639     * This is a convenience method that just delegates to the
1640     * <code>selectionModel</code>.
1641     * The <code>DefaultListSelectionModel</code> implementation
1642     * will do nothing if either <code>index0</code> or
1643     * <code>index1</code> are -1.
1644     * If <code>index0</code> or <code>index1</code> are less than -1,
1645     * <code>IndexOutOfBoundsException</code> is thrown.
1646     *
1647     * @param index0 the first index to remove from the selection
1648     * @param index1 the last index to remove from the selection
1649     * @exception IndexOutOfBoundsException if either <code>index0</code>
1650     * or <code>index1</code> are less than -1
1651     * @see ListSelectionModel#removeSelectionInterval
1652     * @see #setSelectionInterval
1653     * @see #addSelectionInterval
1654     * @see #addListSelectionListener
1655     */

1656    public void removeSelectionInterval(int index0, int index1) {
1657        getSelectionModel().removeSelectionInterval(index0, index1);
1658    }
1659
1660
1661    /**
1662     * Sets the data model's <code>isAdjusting</code> property to true,
1663     * so that a single event will be generated when all of the selection
1664     * events have finished (for example, when the mouse is being
1665     * dragged over the list in selection mode).
1666     *
1667     * @param b the boolean value for the property value
1668     * @see ListSelectionModel#setValueIsAdjusting
1669     */

1670    public void setValueIsAdjusting(boolean b) {
1671        getSelectionModel().setValueIsAdjusting(b);
1672    }
1673
1674
1675    /**
1676     * Returns the value of the data model's <code>isAdjusting</code> property.
1677     * This value is true if multiple changes are being made.
1678     *
1679     * @return true if multiple selection-changes are occurring, as
1680     * when the mouse is being dragged over the list
1681     * @see ListSelectionModel#getValueIsAdjusting
1682     */

1683    public boolean getValueIsAdjusting() {
1684        return getSelectionModel().getValueIsAdjusting();
1685    }
1686
1687
1688    /**
1689     * Returns an array of all of the selected indices in increasing
1690     * order.
1691     *
1692     * @return all of the selected indices, in increasing order
1693     * @see #removeSelectionInterval
1694     * @see #addListSelectionListener
1695     */

1696    public int[] getSelectedIndices() {
1697        ListSelectionModel JavaDoc sm = getSelectionModel();
1698        int iMin = sm.getMinSelectionIndex();
1699        int iMax = sm.getMaxSelectionIndex();
1700
1701        if ((iMin < 0) || (iMax < 0)) {
1702            return new int[0];
1703        }
1704
1705        int[] rvTmp = new int[1+ (iMax - iMin)];
1706        int n = 0;
1707        for(int i = iMin; i <= iMax; i++) {
1708            if (sm.isSelectedIndex(i)) {
1709                rvTmp[n++] = i;
1710            }
1711        }
1712        int[] rv = new int[n];
1713        System.arraycopy(rvTmp, 0, rv, 0, n);
1714        return rv;
1715    }
1716
1717
1718    /**
1719     * Selects a single cell.
1720     *
1721     * @param index the index of the one cell to select
1722     * @see ListSelectionModel#setSelectionInterval
1723     * @see #isSelectedIndex
1724     * @see #addListSelectionListener
1725     * @beaninfo
1726     * description: The index of the selected cell.
1727     */

1728    public void setSelectedIndex(int index) {
1729    if (index >= getModel().getSize()) {
1730        return;
1731    }
1732        getSelectionModel().setSelectionInterval(index, index);
1733    }
1734
1735
1736    /**
1737     * Selects a set of cells.
1738     *
1739     * @param indices an array of the indices of the cells to select
1740     * @see ListSelectionModel#addSelectionInterval
1741     * @see #isSelectedIndex
1742     * @see #addListSelectionListener
1743     */

1744    public void setSelectedIndices(int[] indices) {
1745        ListSelectionModel JavaDoc sm = getSelectionModel();
1746        sm.clearSelection();
1747    int size = getModel().getSize();
1748        for(int i = 0; i < indices.length; i++) {
1749        if (indices[i] < size) {
1750        sm.addSelectionInterval(indices[i], indices[i]);
1751        }
1752        }
1753    }
1754
1755
1756    /**
1757     * Returns an array of the values for the selected cells.
1758     * The returned values are sorted in increasing index order.
1759     *
1760     * @return the selected values or an empty list if
1761     * nothing is selected
1762     * @see #isSelectedIndex
1763     * @see #getModel
1764     * @see #addListSelectionListener
1765     */

1766    public Object JavaDoc[] getSelectedValues() {
1767        ListSelectionModel JavaDoc sm = getSelectionModel();
1768        ListModel JavaDoc dm = getModel();
1769
1770        int iMin = sm.getMinSelectionIndex();
1771        int iMax = sm.getMaxSelectionIndex();
1772
1773        if ((iMin < 0) || (iMax < 0)) {
1774            return new Object JavaDoc[0];
1775        }
1776
1777        Object JavaDoc[] rvTmp = new Object JavaDoc[1+ (iMax - iMin)];
1778        int n = 0;
1779        for(int i = iMin; i <= iMax; i++) {
1780            if (sm.isSelectedIndex(i)) {
1781                rvTmp[n++] = dm.getElementAt(i);
1782            }
1783        }
1784        Object JavaDoc[] rv = new Object JavaDoc[n];
1785        System.arraycopy(rvTmp, 0, rv, 0, n);
1786        return rv;
1787    }
1788
1789
1790    /**
1791     * Returns the first selected index; returns -1 if there is no
1792     * selected item.
1793     *
1794     * @return the value of <code>getMinSelectionIndex</code>
1795     * @see #getMinSelectionIndex
1796     * @see #addListSelectionListener
1797     */

1798    public int getSelectedIndex() {
1799        return getMinSelectionIndex();
1800    }
1801
1802
1803    /**
1804     * Returns the first selected value, or <code>null</code> if the
1805     * selection is empty.
1806     *
1807     * @return the first selected value
1808     * @see #getMinSelectionIndex
1809     * @see #getModel
1810     * @see #addListSelectionListener
1811     */

1812    public Object JavaDoc getSelectedValue() {
1813        int i = getMinSelectionIndex();
1814        return (i == -1) ? null : getModel().getElementAt(i);
1815    }
1816
1817
1818    // PENDING(hmuller) this should move to BasicComboBoxUI
1819
/**
1820     * Selects the specified object from the list.
1821     *
1822     * @param anObject the object to select
1823     * @param shouldScroll true if the list should scroll to display
1824     * the selected object, if one exists; otherwise false
1825     */

1826    public void setSelectedValue(Object JavaDoc anObject,boolean shouldScroll) {
1827        if(anObject == null)
1828            setSelectedIndex(-1);
1829        else if(!anObject.equals(getSelectedValue())) {
1830            int i,c;
1831            ListModel JavaDoc dm = getModel();
1832            for(i=0,c=dm.getSize();i<c;i++)
1833                if(anObject.equals(dm.getElementAt(i))){
1834                    setSelectedIndex(i);
1835                    if(shouldScroll)
1836                        ensureIndexIsVisible(i);
1837                    repaint(); /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
1838                    return;
1839                }
1840            setSelectedIndex(-1);
1841        }
1842        repaint(); /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
1843    }
1844
1845
1846
1847    /**
1848     * --- The Scrollable Implementation ---
1849     */

1850
1851    private void checkScrollableParameters(Rectangle visibleRect, int orientation) {
1852    if (visibleRect == null) {
1853        throw new IllegalArgumentException JavaDoc("visibleRect must be non-null");
1854    }
1855        switch (orientation) {
1856        case SwingConstants.VERTICAL:
1857        case SwingConstants.HORIZONTAL:
1858            break;
1859        default:
1860            throw new IllegalArgumentException JavaDoc("orientation must be one of: VERTICAL, HORIZONTAL");
1861        }
1862    }
1863
1864
1865    /**
1866     * Computes the size of the viewport needed to display
1867     * <code>visibleRowCount</code>
1868     * rows. This is trivial if
1869     * <code>fixedCellWidth</code> and <code>fixedCellHeight</code>
1870     * were specified. Note that they can be specified implicitly with
1871     * the <code>prototypeCellValue</code> property.
1872     * If <code>fixedCellWidth</code> wasn't specified,
1873     * it's computed by finding the widest list element.
1874     * If <code>fixedCellHeight</code>
1875     * wasn't specified then we resort to heuristics:
1876     * <ul>
1877     * <li>
1878     * If the model isn't empty we just multiply the height of the first row
1879     * by <code>visibleRowCount</code>.
1880     * <li>
1881     * If the model is empty, (<code>JList.getModel().getSize() == 0</code>),
1882     * then we just allocate 16 pixels per visible row, and 256 pixels
1883     * for the width (unless <code>fixedCellWidth</code> was set),
1884     * and hope for the best.
1885     * </ul>
1886     * If the layout orientation is not <code>VERTICAL</code>, than this will
1887     * return the value from <code>getPreferredSize</code>. The current
1888     * <code>ListUI</code> is expected to override
1889     * <code>getPreferredSize</code> to return an appropriate value.
1890     *
1891     * @return a dimension containing the size of the viewport needed
1892     * to display <code>visibleRowCount</code> rows
1893     * @see #getPreferredScrollableViewportSize
1894     * @see #setPrototypeCellValue
1895     */

1896    public Dimension getPreferredScrollableViewportSize()
1897    {
1898        if (getLayoutOrientation() != VERTICAL) {
1899            return getPreferredSize();
1900        }
1901        Insets insets = getInsets();
1902        int dx = insets.left + insets.right;
1903        int dy = insets.top + insets.bottom;
1904
1905        int visibleRowCount = getVisibleRowCount();
1906        int fixedCellWidth = getFixedCellWidth();
1907        int fixedCellHeight = getFixedCellHeight();
1908
1909        if ((fixedCellWidth > 0) && (fixedCellHeight > 0)) {
1910            int width = fixedCellWidth + dx;
1911            int height = (visibleRowCount * fixedCellHeight) + dy;
1912            return new Dimension(width, height);
1913        }
1914        else if (getModel().getSize() > 0) {
1915            int width = getPreferredSize().width;
1916            int height;
1917            Rectangle r = getCellBounds(0, 0);
1918            if (r != null) {
1919                height = (visibleRowCount * r.height) + dy;
1920            }
1921            else {
1922                // Will only happen if UI null, shouldn't matter what we return
1923
height = 1;
1924            }
1925            return new Dimension(width, height);
1926        }
1927        else {
1928            fixedCellWidth = (fixedCellWidth > 0) ? fixedCellWidth : 256;
1929            fixedCellHeight = (fixedCellHeight > 0) ? fixedCellHeight : 16;
1930            return new Dimension(fixedCellWidth, fixedCellHeight * visibleRowCount);
1931        }
1932    }
1933
1934
1935    /**
1936     * Returns the distance to scroll to expose the next or previous
1937     * row (for vertical scrolling) or column (for horizontal scrolling).
1938     * <p>
1939     * For horizontal scrolling if the list is layed out vertically
1940     * (the orientation is <code>VERTICAL</code>) than the lists font size
1941     * or 1 is returned if the font is <code>null</code> is used.
1942     * <p>
1943     * Note that the value of <code>visibleRect</code> must be the equal to
1944     * <code>this.getVisibleRect()</code>.
1945     *
1946     * @param visibleRect the visible rectangle
1947     * @param orientation HORIZONTAL or VERTICAL
1948     * @param direction if <= 0, then scroll UP; if > 0, then scroll DOWN
1949     * @return the distance, in pixels, to scroll to expose the
1950     * next or previous unit
1951     * @see Scrollable#getScrollableUnitIncrement
1952     * @throws IllegalArgumentException if visibleRect is <code>null<code>, or
1953     * orientation isn't one of SwingConstants.VERTICAL,
1954     * SwingConstants.HORIZONTAL.
1955     *
1956     */

1957    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
1958    {
1959    checkScrollableParameters(visibleRect, orientation);
1960
1961        if (orientation == SwingConstants.VERTICAL) {
1962            int row = getFirstVisibleIndex();
1963
1964            if (row == -1) {
1965                return 0;
1966            }
1967            else {
1968                /* Scroll Down */
1969                if (direction > 0) {
1970                    Rectangle r = getCellBounds(row, row);
1971                    return (r == null) ? 0 : r.height - (visibleRect.y - r.y);
1972                }
1973                /* Scroll Up */
1974                else {
1975                    Rectangle r = getCellBounds(row, row);
1976
1977                    /* The first row is completely visible and it's row 0.
1978                     * We're done.
1979                     */

1980                    if ((r.y == visibleRect.y) && (row == 0)) {
1981                        return 0;
1982                    }
1983                    /* The first row is completely visible, return the
1984                     * height of the previous row or 0 if the first row
1985                     * is the top row of the list.
1986                     */

1987                    else if (r.y == visibleRect.y) {
1988            Point loc = r.getLocation();
1989            loc.y--;
1990            int prevIndex = locationToIndex(loc);
1991                        Rectangle prevR = getCellBounds(prevIndex, prevIndex);
1992
1993                        if (prevR == null || prevR.y >= r.y) {
1994                            return 0;
1995                        }
1996                        return prevR.height;
1997                    }
1998                    /* The first row is partially visible, return the
1999                     * height of hidden part.
2000                     */

2001                    else {
2002                        return visibleRect.y - r.y;
2003                    }
2004                }
2005            }
2006        } else if (orientation == SwingConstants.HORIZONTAL &&
2007                           getLayoutOrientation() != JList.VERTICAL) {
2008        int index = locationToIndex(visibleRect.getLocation());
2009
2010            if (index != -1) {
2011                Rectangle cellBounds = getCellBounds(index, index);
2012
2013                if (cellBounds != null) {
2014                    if (cellBounds.x != visibleRect.x) {
2015                        if (direction < 0) {
2016                            return Math.abs(cellBounds.x - visibleRect.x);
2017                        }
2018                        return cellBounds.width + cellBounds.x - visibleRect.x;
2019                    }
2020                    return cellBounds.width;
2021                }
2022            }
2023        }
2024    Font f = getFont();
2025    return (f != null) ? f.getSize() : 1;
2026    }
2027
2028
2029    /**
2030     * Returns the distance to scroll to expose the next or previous block.
2031     * For vertical scrolling we are using the follows rules:
2032     * <ul>
2033     * <li>if scrolling down (<code>direction</code> is greater than 0),
2034     * the last visible element should become the first completely
2035     * visible element
2036     * <li>if scrolling up, the first visible element should become the last
2037     * completely visible element
2038     * <li>visibleRect.height if the list is empty
2039     * </ul>
2040     * <p>
2041     * For horizontal scrolling if the list is layed out horizontally
2042     * (the orientation is <code>VERTICAL_WRAP</code> or
2043     * <code>HORIZONTAL_WRAP</code>):
2044     * <ul>
2045     * </ul>
2046     * <li>if scrolling right (<code>direction</code> is greater than 0),
2047     * the last visible element should become the first completely
2048     * visible element
2049     * <li>if scrolling left, the first visible element should become the last
2050     * completely visible element
2051     * <li>visibleRect.width if the list is empty
2052     * <p>
2053     * Return visibleRect.width if the list is layed out vertically.
2054     * <p>
2055     * Note that the value of <code>visibleRect</code> must be the equal to
2056     * <code>this.getVisibleRect()</code>.
2057     *
2058     * @param visibleRect the visible rectangle
2059     * @param orientation HORIZONTAL or VERTICAL
2060     * @param direction if <= 0, then scroll UP; if > 0, then scroll DOWN
2061     * @return the block increment amount.
2062     * @see Scrollable#getScrollableUnitIncrement
2063     * @throws IllegalArgumentException if visibleRect is <code>null</code>, or
2064     * orientation isn't one of SwingConstants.VERTICAL,
2065     * SwingConstants.HORIZONTAL.
2066     *
2067     */

2068    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
2069    checkScrollableParameters(visibleRect, orientation);
2070        if (orientation == SwingConstants.VERTICAL) {
2071            int inc = visibleRect.height;
2072            /* Scroll Down */
2073            if (direction > 0) {
2074                // last cell is the lowest left cell
2075
int last = locationToIndex(new Point(visibleRect.x, visibleRect.y+visibleRect.height-1));
2076                if (last != -1) {
2077            Rectangle lastRect = getCellBounds(last,last);
2078            if (lastRect != null) {
2079            inc = lastRect.y - visibleRect.y;
2080            if ( (inc == 0) && (last < getModel().getSize()-1) ) {
2081                inc = lastRect.height;
2082            }
2083            }
2084                }
2085            }
2086            /* Scroll Up */
2087            else {
2088                int newFirst = locationToIndex(new Point(visibleRect.x, visibleRect.y-visibleRect.height));
2089                int first = getFirstVisibleIndex();
2090                if (newFirst != -1) {
2091            if (first == -1) {
2092            first = locationToIndex(visibleRect.getLocation());
2093            }
2094                    Rectangle newFirstRect = getCellBounds(newFirst,newFirst);
2095                    Rectangle firstRect = getCellBounds(first,first);
2096            if ((newFirstRect != null) && (firstRect!=null)) {
2097            while ( (newFirstRect.y + visibleRect.height <
2098                 firstRect.y + firstRect.height) &&
2099                (newFirstRect.y < firstRect.y) ) {
2100                newFirst++;
2101                newFirstRect = getCellBounds(newFirst,newFirst);
2102            }
2103            inc = visibleRect.y - newFirstRect.y;
2104            if ( (inc <= 0) && (newFirstRect.y > 0)) {
2105                newFirst--;
2106                newFirstRect = getCellBounds(newFirst,newFirst);
2107                if (newFirstRect != null) {
2108                inc = visibleRect.y - newFirstRect.y;
2109                }
2110            }
2111            }
2112        }
2113            }
2114            return inc;
2115        }
2116    else if (orientation == SwingConstants.HORIZONTAL &&
2117         getLayoutOrientation() != JList.VERTICAL) {
2118        int inc = visibleRect.width;
2119        /* Scroll Right */
2120        if (direction > 0) {
2121        // last cell is an upper right cell
2122
int last = locationToIndex(new Point(visibleRect.x + visibleRect.width - 1,
2123                             visibleRect.y));
2124        if (last != -1) {
2125            Rectangle lastRect = getCellBounds(last,last);
2126            if (lastRect != null) {
2127            inc = lastRect.x - visibleRect.x;
2128            if (inc < 0) {
2129                inc += lastRect.width;
2130            } else if ( (inc == 0) && (last < getModel().getSize()-1) ) {
2131                inc = lastRect.width;
2132            }
2133            }
2134        }
2135        }
2136        /* Scroll Left */
2137        else {
2138        // first cell is a cell at the upper left corner of the visibleRect
2139
// shifted left by the visibleRect.width
2140
int first = locationToIndex(new Point(visibleRect.x - visibleRect.width,
2141                             visibleRect.y));
2142        if (first != -1) {
2143            Rectangle firstRect = getCellBounds(first,first);
2144            if (firstRect != null) {
2145            if (firstRect.x < visibleRect.x - visibleRect.width) {
2146                if (firstRect.x + firstRect.width >= visibleRect.x) {
2147                inc = visibleRect.x - firstRect.x;
2148                } else {
2149                inc = visibleRect.x - firstRect.x - firstRect.width;
2150                }
2151            } else {
2152                inc = visibleRect.x - firstRect.x;
2153            }
2154            }
2155        }
2156        }
2157        return inc;
2158    }
2159        return visibleRect.width;
2160    }
2161
2162
2163    /**
2164     * Returns true if this <code>JList</code> is displayed in a
2165     * <code>JViewport</code> and the viewport is wider than
2166     * <code>JList</code>'s preferred width; or if the
2167     * layout orientation is <code>HORIZONTAL_WRAP</code> and the
2168     * visible row count is <= 0; otherwise returns
2169     * false.
2170     * If false, then don't track the viewport's width. This allows horizontal
2171     * scrolling if the <code>JViewport</code> is itself embedded in a
2172     * <code>JScrollPane</code>.
2173     *
2174     * @return true if viewport is wider than the <code>JList</code>'s
2175     * preferred width, otherwise false
2176     * @see Scrollable#getScrollableTracksViewportWidth
2177     */

2178    public boolean getScrollableTracksViewportWidth() {
2179        if (getLayoutOrientation() == HORIZONTAL_WRAP &&
2180                                      getVisibleRowCount() <= 0) {
2181            return true;
2182        }
2183    if (getParent() instanceof JViewport JavaDoc) {
2184        return (((JViewport JavaDoc)getParent()).getWidth() > getPreferredSize().width);
2185    }
2186    return false;
2187    }
2188
2189    /**
2190     * Returns true if this <code>JList</code> is displayed in a
2191     * <code>JViewport</code> and the viewport is taller than
2192     * <code>JList</code>'s preferred height, or if the layout orientation is
2193     * <code>VERTICAL_WRAP</code> and the number of visible rows is <= 0;
2194     * otherwise returns false.
2195     * If false, then don't track the viewport's height. This allows vertical
2196     * scrolling if the <code>JViewport</code> is itself embedded in a
2197     * <code>JScrollPane</code>.
2198     *
2199     * @return true if viewport is taller than <code>Jlist</code>'s
2200     * preferred height, otherwise false
2201     * @see Scrollable#getScrollableTracksViewportHeight
2202     */

2203    public boolean getScrollableTracksViewportHeight() {
2204        if (getLayoutOrientation() == VERTICAL_WRAP &&
2205                     getVisibleRowCount() <= 0) {
2206            return true;
2207        }
2208    if (getParent() instanceof JViewport JavaDoc) {
2209        return (((JViewport JavaDoc)getParent()).getHeight() > getPreferredSize().height);
2210    }
2211    return false;
2212    }
2213
2214
2215    /*
2216     * See readObject and writeObject in JComponent for more
2217     * information about serialization in Swing.
2218     */

2219    private void writeObject(ObjectOutputStream JavaDoc s) throws IOException JavaDoc {
2220        s.defaultWriteObject();
2221        if (getUIClassID().equals(uiClassID)) {
2222            byte count = JComponent.getWriteObjCounter(this);
2223            JComponent.setWriteObjCounter(this, --count);
2224            if (count == 0 && ui != null) {
2225                ui.installUI(this);
2226            }
2227        }
2228    }
2229
2230
2231    /**
2232     * Returns a string representation of this <code>JList</code>.
2233     * This method
2234     * is intended to be used only for debugging purposes, and the
2235     * content and format of the returned string may vary between
2236     * implementations. The returned string may be empty but may not
2237     * be <code>null</code>.
2238     *
2239     * @return a string representation of this <code>JList</code>.
2240     */

2241    protected String JavaDoc paramString() {
2242        String JavaDoc selectionForegroundString = (selectionForeground != null ?
2243                                            selectionForeground.toString() :
2244                                            "");
2245        String JavaDoc selectionBackgroundString = (selectionBackground != null ?
2246                                            selectionBackground.toString() :
2247                                            "");
2248
2249    return super.paramString() +
2250        ",fixedCellHeight=" + fixedCellHeight +
2251        ",fixedCellWidth=" + fixedCellWidth +
2252        ",horizontalScrollIncrement=" + horizontalScrollIncrement +
2253        ",selectionBackground=" + selectionBackgroundString +
2254        ",selectionForeground=" + selectionForegroundString +
2255        ",visibleRowCount=" + visibleRowCount +
2256        ",layoutOrientation=" + layoutOrientation;
2257    }
2258
2259
2260    /**
2261     * --- Accessibility Support ---
2262     */

2263
2264    /**
2265     * Gets the AccessibleContext associated with this JList.
2266     * For JLists, the AccessibleContext takes the form of an
2267     * AccessibleJList.
2268     * A new AccessibleJList instance is created if necessary.
2269     *
2270     * @return an AccessibleJList that serves as the
2271     * AccessibleContext of this JList
2272     */

2273    public AccessibleContext getAccessibleContext() {
2274        if (accessibleContext == null) {
2275            accessibleContext = new AccessibleJList();
2276        }
2277        return accessibleContext;
2278    }
2279
2280    /**
2281     * This class implements accessibility support for the
2282     * <code>JList</code> class. It provides an implementation of the
2283     * Java Accessibility API appropriate to list user-interface
2284     * elements.
2285     * <p>
2286     * <strong>Warning:</strong>
2287     * Serialized objects of this class will not be compatible with
2288     * future Swing releases. The current serialization support is
2289     * appropriate for short term storage or RMI between applications running
2290     * the same version of Swing. As of 1.4, support for long term storage
2291     * of all JavaBeans<sup><font size="-2">TM</font></sup>
2292     * has been added to the <code>java.beans</code> package.
2293     * Please see {@link java.beans.XMLEncoder}.
2294     */

2295    protected class AccessibleJList extends AccessibleJComponent
2296        implements AccessibleSelection, PropertyChangeListener,
2297    ListSelectionListener, ListDataListener {
2298
2299    int leadSelectionIndex;
2300
2301        public AccessibleJList() {
2302            super();
2303            JList.this.addPropertyChangeListener(this);
2304            JList.this.getSelectionModel().addListSelectionListener(this);
2305            JList.this.getModel().addListDataListener(this);
2306            leadSelectionIndex = JList.this.getLeadSelectionIndex();
2307        }
2308
2309        /**
2310         * Property Change Listener change method. Used to track changes
2311     * to the DataModel and ListSelectionModel, in order to re-set
2312     * listeners to those for reporting changes there via the Accessibility
2313     * PropertyChange mechanism.
2314         *
2315         * @param e PropertyChangeEvent
2316         */

2317        public void propertyChange(PropertyChangeEvent e) {
2318            String JavaDoc name = e.getPropertyName();
2319            Object JavaDoc oldValue = e.getOldValue();
2320            Object JavaDoc newValue = e.getNewValue();
2321
2322                // re-set listData listeners
2323
if (name.compareTo("model") == 0) {
2324
2325                if (oldValue != null && oldValue instanceof ListModel JavaDoc) {
2326                    ((ListModel JavaDoc) oldValue).removeListDataListener(this);
2327                }
2328                if (newValue != null && newValue instanceof ListModel JavaDoc) {
2329                    ((ListModel JavaDoc) newValue).addListDataListener(this);
2330                }
2331
2332                // re-set listSelectionModel listeners
2333
} else if (name.compareTo("selectionModel") == 0) {
2334
2335                if (oldValue != null && oldValue instanceof ListSelectionModel JavaDoc) {
2336                    ((ListSelectionModel JavaDoc) oldValue).removeListSelectionListener(this);
2337                }
2338                if (newValue != null && newValue instanceof ListSelectionModel JavaDoc) {
2339                    ((ListSelectionModel JavaDoc) newValue).addListSelectionListener(this);
2340                }
2341
2342        firePropertyChange(
2343            AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
2344            Boolean.valueOf(false), Boolean.valueOf(true));
2345        }
2346    }
2347
2348        /**
2349         * List Selection Listener value change method. Used to fire
2350     * the property change
2351         *
2352         * @param e ListSelectionEvent
2353         *
2354         */

2355        public void valueChanged(ListSelectionEvent e) {
2356        int oldLeadSelectionIndex = leadSelectionIndex;
2357            leadSelectionIndex = JList.this.getLeadSelectionIndex();
2358        if (oldLeadSelectionIndex != leadSelectionIndex) {
2359        Accessible oldLS, newLS;
2360        oldLS = (oldLeadSelectionIndex >= 0)
2361            ? getAccessibleChild(oldLeadSelectionIndex)
2362            : null;
2363        newLS = (leadSelectionIndex >= 0)
2364            ? getAccessibleChild(leadSelectionIndex)
2365            : null;
2366                firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY,
2367                                   oldLS, newLS);
2368        }
2369
2370            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
2371                               Boolean.valueOf(false), Boolean.valueOf(true));
2372            firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
2373                               Boolean.valueOf(false), Boolean.valueOf(true));
2374
2375            // Process the State changes for Multiselectable
2376
AccessibleStateSet s = getAccessibleStateSet();
2377            ListSelectionModel JavaDoc lsm = JList.this.getSelectionModel();
2378            if (lsm.getSelectionMode() != ListSelectionModel.SINGLE_SELECTION) {
2379                if (!s.contains(AccessibleState.MULTISELECTABLE)) {
2380                    s.add(AccessibleState.MULTISELECTABLE);
2381                    firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
2382                                       null, AccessibleState.MULTISELECTABLE);
2383                }
2384            } else {
2385                if (s.contains(AccessibleState.MULTISELECTABLE)) {
2386                    s.remove(AccessibleState.MULTISELECTABLE);
2387                    firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
2388                                       AccessibleState.MULTISELECTABLE, null);
2389                }
2390            }
2391        }
2392
2393        /**
2394         * List Data Listener interval added method. Used to fire the visible data property change
2395         *
2396         * @param e ListDataEvent
2397         *
2398         */

2399        public void intervalAdded(ListDataEvent e) {
2400            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
2401                               Boolean.valueOf(false), Boolean.valueOf(true));
2402        }
2403
2404        /**
2405         * List Data Listener interval removed method. Used to fire the visible data property change
2406         *
2407         * @param e ListDataEvent
2408         *
2409         */

2410        public void intervalRemoved(ListDataEvent e) {
2411            firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
2412                               Boolean.valueOf(false), Boolean.valueOf(true));
2413        }
2414
2415        /**
2416         * List Data Listener contents changed method. Used to fire the visible data property change
2417         *
2418         * @param e ListDataEvent
2419         *
2420         */

2421         public void contentsChanged(ListDataEvent e) {
2422             firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
2423                                Boolean.valueOf(false), Boolean.valueOf(true));
2424         }
2425
2426    // AccessibleContext methods
2427

2428        /**
2429         * Get the state set of this object.
2430         *
2431         * @return an instance of AccessibleState containing the current state
2432         * of the object
2433         * @see AccessibleState
2434         */

2435        public AccessibleStateSet getAccessibleStateSet() {
2436            AccessibleStateSet states = super.getAccessibleStateSet();
2437            if (selectionModel.getSelectionMode() !=
2438                ListSelectionModel.SINGLE_SELECTION) {
2439                states.add(AccessibleState.MULTISELECTABLE);
2440            }
2441            return states;
2442        }
2443
2444        /**
2445         * Get the role of this object.
2446         *
2447         * @return an instance of AccessibleRole describing the role of the
2448         * object
2449         * @see AccessibleRole
2450         */

2451        public AccessibleRole getAccessibleRole() {
2452            return AccessibleRole.LIST;
2453        }
2454
2455        /**
2456         * Returns the <code>Accessible</code> child contained at
2457         * the local coordinate <code>Point</code>, if one exists.
2458         * Otherwise returns <code>null</code>.
2459         *
2460         * @return the <code>Accessible</code> at the specified
2461         * location, if it exists
2462         */

2463        public Accessible getAccessibleAt(Point p) {
2464            int i = locationToIndex(p);
2465            if (i >= 0) {
2466                return new AccessibleJListChild(JList.this, i);
2467            } else {
2468                return null;
2469            }
2470        }
2471
2472        /**
2473         * Returns the number of accessible children in the object. If all
2474         * of the children of this object implement Accessible, than this
2475         * method should return the number of children of this object.
2476         *
2477         * @return the number of accessible children in the object.
2478         */

2479        public int getAccessibleChildrenCount() {
2480            return getModel().getSize();
2481        }
2482
2483        /**
2484         * Return the nth Accessible child of the object.
2485         *
2486         * @param i zero-based index of child
2487         * @return the nth Accessible child of the object
2488         */

2489        public Accessible getAccessibleChild(int i) {
2490            if (i >= getModel().getSize()) {
2491                return null;
2492            } else {
2493                return new AccessibleJListChild(JList.this, i);
2494            }
2495        }
2496
2497        /**
2498         * Get the AccessibleSelection associated with this object. In the
2499         * implementation of the Java Accessibility API for this class,
2500     * return this object, which is responsible for implementing the
2501         * AccessibleSelection interface on behalf of itself.
2502     *
2503     * @return this object
2504         */

2505        public AccessibleSelection getAccessibleSelection() {
2506            return this;
2507        }
2508
2509
2510    // AccessibleSelection methods
2511

2512        /**
2513         * Returns the number of items currently selected.
2514         * If no items are selected, the return value will be 0.
2515         *
2516         * @return the number of items currently selected.
2517         */

2518         public int getAccessibleSelectionCount() {
2519             return JList.this.getSelectedIndices().length;
2520         }
2521
2522        /**
2523         * Returns an Accessible representing the specified selected item
2524         * in the object. If there isn't a selection, or there are
2525         * fewer items selected than the integer passed in, the return
2526         * value will be <code>null</code>.
2527         *
2528         * @param i the zero-based index of selected items
2529         * @return an Accessible containing the selected item
2530         */

2531         public Accessible getAccessibleSelection(int i) {
2532             int len = getAccessibleSelectionCount();
2533             if (i < 0 || i >= len) {
2534                 return null;
2535             } else {
2536                 return getAccessibleChild(JList.this.getSelectedIndices()[i]);
2537             }
2538         }
2539
2540        /**
2541         * Returns true if the current child of this object is selected.
2542         *
2543         * @param i the zero-based index of the child in this Accessible
2544         * object.
2545         * @see AccessibleContext#getAccessibleChild
2546         */

2547        public boolean isAccessibleChildSelected(int i) {
2548            return isSelectedIndex(i);
2549        }
2550
2551        /**
2552         * Adds the specified selected item in the object to the object's
2553         * selection. If the object supports multiple selections,
2554         * the specified item is added to any existing selection, otherwise
2555         * it replaces any existing selection in the object. If the
2556         * specified item is already selected, this method has no effect.
2557         *
2558         * @param i the zero-based index of selectable items
2559         */

2560         public void addAccessibleSelection(int i) {
2561             JList.this.addSelectionInterval(i, i);
2562         }
2563
2564        /**
2565         * Removes the specified selected item in the object from the object's
2566         * selection. If the specified item isn't currently selected, this
2567         * method has no effect.
2568         *
2569         * @param i the zero-based index of selectable items
2570         */

2571         public void removeAccessibleSelection(int i) {
2572             JList.this.removeSelectionInterval(i, i);
2573         }
2574
2575        /**
2576         * Clears the selection in the object, so that nothing in the
2577         * object is selected.
2578         */

2579         public void clearAccessibleSelection() {
2580             JList.this.clearSelection();
2581         }
2582
2583        /**
2584         * Causes every selected item in the object to be selected
2585         * if the object supports multiple selections.
2586         */

2587         public void selectAllAccessibleSelection() {
2588             JList.this.addSelectionInterval(0, getAccessibleChildrenCount() -1);
2589         }
2590
2591      /**
2592       * This class implements accessibility support appropriate
2593       * for list children.
2594       */

2595        protected class AccessibleJListChild extends AccessibleContext
2596                implements Accessible, AccessibleComponent {
2597            private JList JavaDoc parent = null;
2598            private int indexInParent;
2599            private Component component = null;
2600            private AccessibleContext accessibleContext = null;
2601            private ListModel JavaDoc listModel;
2602            private ListCellRenderer JavaDoc cellRenderer = null;
2603
2604            public AccessibleJListChild(JList JavaDoc parent, int indexInParent) {
2605                this.parent = parent;
2606                this.setAccessibleParent(parent);
2607                this.indexInParent = indexInParent;
2608                if (parent != null) {
2609                    listModel = parent.getModel();
2610                    cellRenderer = parent.getCellRenderer();
2611                }
2612            }
2613
2614            private Component getCurrentComponent() {
2615                return getComponentAtIndex(indexInParent);
2616            }
2617
2618            private AccessibleContext getCurrentAccessibleContext() {
2619                Component c = getComponentAtIndex(indexInParent);
2620                if (c instanceof Accessible) {
2621                    return ((Accessible) c).getAccessibleContext();
2622                } else {
2623                    return null;
2624                }
2625            }
2626
2627            private Component getComponentAtIndex(int index) {
2628                if (index < 0 || index >= listModel.getSize()) {
2629                    return null;
2630                }
2631                if ((parent != null)
2632                        && (listModel != null)
2633                        && cellRenderer != null) {
2634                    Object JavaDoc value = listModel.getElementAt(index);
2635                    boolean isSelected = parent.isSelectedIndex(index);
2636                    boolean isFocussed = parent.isFocusOwner()
2637                            && (index == parent.getLeadSelectionIndex());
2638                    return cellRenderer.getListCellRendererComponent(
2639                            parent,
2640                            value,
2641                            index,
2642                            isSelected,
2643                            isFocussed);
2644                } else {
2645                    return null;
2646                }
2647            }
2648
2649
2650            // Accessible Methods
2651
/**
2652        * Get the AccessibleContext for this object. In the
2653        * implementation of the Java Accessibility API for this class,
2654        * returns this object, which is its own AccessibleContext.
2655        *
2656        * @return this object
2657        */

2658            public AccessibleContext getAccessibleContext() {
2659                return this;
2660            }
2661
2662
2663            // AccessibleContext methods
2664

2665            public String JavaDoc getAccessibleName() {
2666                AccessibleContext ac = getCurrentAccessibleContext();
2667                if (ac != null) {
2668                    return ac.getAccessibleName();
2669                } else {
2670                    return null;
2671                }
2672            }
2673
2674            public void setAccessibleName(String JavaDoc s) {
2675                AccessibleContext ac = getCurrentAccessibleContext();
2676                if (ac != null) {
2677                    ac.setAccessibleName(s);
2678                }
2679            }
2680
2681            public String JavaDoc getAccessibleDescription() {
2682                AccessibleContext ac = getCurrentAccessibleContext();
2683                if (ac != null) {
2684                    return ac.getAccessibleDescription();
2685                } else {
2686                    return null;
2687                }
2688            }
2689
2690            public void setAccessibleDescription(String JavaDoc s) {
2691                AccessibleContext ac = getCurrentAccessibleContext();
2692                if (ac != null) {
2693                    ac.setAccessibleDescription(s);
2694                }
2695            }
2696
2697            public AccessibleRole getAccessibleRole() {
2698                AccessibleContext ac = getCurrentAccessibleContext();
2699                if (ac != null) {
2700                    return ac.getAccessibleRole();
2701                } else {
2702                    return null;
2703                }
2704            }
2705
2706            public AccessibleStateSet getAccessibleStateSet() {
2707                AccessibleContext ac = getCurrentAccessibleContext();
2708                AccessibleStateSet s;
2709                if (ac != null) {
2710                    s = ac.getAccessibleStateSet();
2711                } else {
2712                    s = new AccessibleStateSet();
2713                }
2714                s = ac.getAccessibleStateSet();
2715                s.add(AccessibleState.SELECTABLE);
2716            if (parent.isFocusOwner()
2717            && (indexInParent == parent.getLeadSelectionIndex())) {
2718                    s.add(AccessibleState.ACTIVE);
2719            }
2720                if (parent.isSelectedIndex(indexInParent)) {
2721                    s.add(AccessibleState.SELECTED);
2722                }
2723                if (this.isShowing()) {
2724                    s.add(AccessibleState.SHOWING);
2725                } else if (s.contains(AccessibleState.SHOWING)) {
2726                    s.remove(AccessibleState.SHOWING);
2727                }
2728                if (this.isVisible()) {
2729                    s.add(AccessibleState.VISIBLE);
2730                } else if (s.contains(AccessibleState.VISIBLE)) {
2731                    s.remove(AccessibleState.VISIBLE);
2732                }
2733                s.add(AccessibleState.TRANSIENT); // cell-rendered
2734
return s;
2735            }
2736
2737            public int getAccessibleIndexInParent() {
2738                return indexInParent;
2739            }
2740
2741            public int getAccessibleChildrenCount() {
2742                AccessibleContext ac = getCurrentAccessibleContext();
2743                if (ac != null) {
2744                    return ac.getAccessibleChildrenCount();
2745                } else {
2746                    return 0;
2747                }
2748            }
2749
2750            public Accessible getAccessibleChild(int i) {
2751                AccessibleContext ac = getCurrentAccessibleContext();
2752                if (ac != null) {
2753                    Accessible accessibleChild = ac.getAccessibleChild(i);
2754                    ac.setAccessibleParent(this);
2755                    return accessibleChild;
2756                } else {
2757                    return null;
2758                }
2759            }
2760
2761            public Locale JavaDoc getLocale() {
2762                AccessibleContext ac = getCurrentAccessibleContext();
2763                if (ac != null) {
2764                    return ac.getLocale();
2765                } else {
2766                    return null;
2767                }
2768            }
2769
2770            public void addPropertyChangeListener(PropertyChangeListener l) {
2771                AccessibleContext ac = getCurrentAccessibleContext();
2772                if (ac != null) {
2773                    ac.addPropertyChangeListener(l);
2774                }
2775            }
2776
2777            public void removePropertyChangeListener(PropertyChangeListener l) {
2778                AccessibleContext ac = getCurrentAccessibleContext();
2779                if (ac != null) {
2780                    ac.removePropertyChangeListener(l);
2781                }
2782            }
2783
2784            public AccessibleAction getAccessibleAction() {
2785                return getCurrentAccessibleContext().getAccessibleAction();
2786            }
2787
2788       /**
2789            * Get the AccessibleComponent associated with this object. In the
2790            * implementation of the Java Accessibility API for this class,
2791        * return this object, which is responsible for implementing the
2792            * AccessibleComponent interface on behalf of itself.
2793        *
2794        * @return this object
2795        */

2796            public AccessibleComponent getAccessibleComponent() {
2797                return this; // to override getBounds()
2798
}
2799
2800            public AccessibleSelection getAccessibleSelection() {
2801                return getCurrentAccessibleContext().getAccessibleSelection();
2802            }
2803
2804            public AccessibleText getAccessibleText() {
2805                return getCurrentAccessibleContext().getAccessibleText();
2806            }
2807
2808            public AccessibleValue getAccessibleValue() {
2809                return getCurrentAccessibleContext().getAccessibleValue();
2810            }
2811
2812
2813            // AccessibleComponent methods
2814

2815            public Color getBackground() {
2816                AccessibleContext ac = getCurrentAccessibleContext();
2817                if (ac instanceof AccessibleComponent) {
2818                    return ((AccessibleComponent) ac).getBackground();
2819                } else {
2820                    Component c = getCurrentComponent();
2821                    if (c != null) {
2822                        return c.getBackground();
2823                    } else {
2824                        return null;
2825                    }
2826                }
2827            }
2828
2829            public void setBackground(Color c) {
2830                AccessibleContext ac = getCurrentAccessibleContext();
2831                if (ac instanceof AccessibleComponent) {
2832                    ((AccessibleComponent) ac).setBackground(c);
2833                } else {
2834                    Component cp = getCurrentComponent();
2835                    if (cp != null) {
2836                        cp.setBackground(c);
2837                    }
2838                }
2839            }
2840
2841            public Color getForeground() {
2842                AccessibleContext ac = getCurrentAccessibleContext();
2843                if (ac instanceof AccessibleComponent) {
2844                    return ((AccessibleComponent) ac).getForeground();
2845                } else {
2846                    Component c = getCurrentComponent();
2847                    if (c != null) {
2848                        return c.getForeground();
2849                    } else {
2850                        return null;
2851                    }
2852                }
2853            }
2854
2855            public void setForeground(Color c) {
2856                AccessibleContext ac = getCurrentAccessibleContext();
2857                if (ac instanceof AccessibleComponent) {
2858                    ((AccessibleComponent) ac).setForeground(c);
2859                } else {
2860                    Component cp = getCurrentComponent();
2861                    if (cp != null) {
2862                        cp.setForeground(c);
2863                    }
2864                }
2865            }
2866
2867            public Cursor getCursor() {
2868                AccessibleContext ac = getCurrentAccessibleContext();
2869                if (ac instanceof AccessibleComponent) {
2870                    return ((AccessibleComponent) ac).getCursor();
2871                } else {
2872                    Component c = getCurrentComponent();
2873                    if (c != null) {
2874                        return c.getCursor();
2875                    } else {
2876                        Accessible ap = getAccessibleParent();
2877                        if (ap instanceof AccessibleComponent) {
2878                            return ((AccessibleComponent) ap).getCursor();
2879                        } else {
2880                            return null;
2881                        }
2882                    }
2883                }
2884            }
2885
2886            public void setCursor(Cursor c) {
2887                AccessibleContext ac = getCurrentAccessibleContext();
2888                if (ac instanceof AccessibleComponent) {
2889                    ((AccessibleComponent) ac).setCursor(c);
2890                } else {
2891                    Component cp = getCurrentComponent();
2892                    if (cp != null) {
2893                        cp.setCursor(c);
2894                    }
2895                }
2896            }
2897
2898            public Font getFont() {
2899                AccessibleContext ac = getCurrentAccessibleContext();
2900                if (ac instanceof AccessibleComponent) {
2901                    return ((AccessibleComponent) ac).getFont();
2902                } else {
2903                    Component c = getCurrentComponent();
2904                    if (c != null) {
2905                        return c.getFont();
2906                    } else {
2907                        return null;
2908                    }
2909                }
2910            }
2911
2912            public void setFont(Font f) {
2913                AccessibleContext ac = getCurrentAccessibleContext();
2914                if (ac instanceof AccessibleComponent) {
2915                    ((AccessibleComponent) ac).setFont(f);
2916                } else {
2917                    Component c = getCurrentComponent();
2918                    if (c != null) {
2919                        c.setFont(f);
2920                    }
2921                }
2922            }
2923
2924            public FontMetrics getFontMetrics(Font f) {
2925                AccessibleContext ac = getCurrentAccessibleContext();
2926                if (ac instanceof AccessibleComponent) {
2927                    return ((AccessibleComponent) ac).getFontMetrics(f);
2928                } else {
2929                    Component c = getCurrentComponent();
2930                    if (c != null) {
2931                        return c.getFontMetrics(f);
2932                    } else {
2933                        return null;
2934                    }
2935                }
2936            }
2937
2938            public boolean isEnabled() {
2939                AccessibleContext ac = getCurrentAccessibleContext();
2940                if (ac instanceof AccessibleComponent) {
2941                    return ((AccessibleComponent) ac).isEnabled();
2942                } else {
2943                    Component c = getCurrentComponent();
2944                    if (c != null) {
2945                        return c.isEnabled();
2946                    } else {
2947                        return false;
2948                    }
2949                }
2950            }
2951
2952            public void setEnabled(boolean b) {
2953                AccessibleContext ac = getCurrentAccessibleContext();
2954                if (ac instanceof AccessibleComponent) {
2955                    ((AccessibleComponent) ac).setEnabled(b);
2956                } else {
2957                    Component c = getCurrentComponent();
2958                    if (c != null) {
2959                        c.setEnabled(b);
2960                    }
2961                }
2962            }
2963
2964            public boolean isVisible() {
2965                int fi = parent.getFirstVisibleIndex();
2966                int li = parent.getLastVisibleIndex();
2967                // The UI incorrectly returns a -1 for the last
2968
// visible index if the list is smaller than the
2969
// viewport size.
2970
if (li == -1) {
2971                    li = parent.getModel().getSize() - 1;
2972                }
2973                return ((indexInParent >= fi)
2974                        && (indexInParent <= li));
2975            }
2976
2977            public void setVisible(boolean b) {
2978            }
2979
2980            public boolean isShowing() {
2981                return (parent.isShowing() && isVisible());
2982            }
2983
2984            public boolean contains(Point p) {
2985                AccessibleContext ac = getCurrentAccessibleContext();
2986                if (ac instanceof AccessibleComponent) {
2987                    Rectangle r = ((AccessibleComponent) ac).getBounds();
2988                    return r.contains(p);
2989                } else {
2990                    Component c = getCurrentComponent();
2991                    if (c != null) {
2992                        Rectangle r = c.getBounds();
2993                        return r.contains(p);
2994                    } else {
2995                        return getBounds().contains(p);
2996                    }
2997                }
2998            }
2999
3000            public Point getLocationOnScreen() {
3001                if (parent != null) {
3002                    Point listLocation = parent.getLocationOnScreen();
3003                    Point componentLocation = parent.indexToLocation(indexInParent);
3004            if (componentLocation != null) {
3005            componentLocation.translate(listLocation.x, listLocation.y);
3006            return componentLocation;
3007            } else {
3008            return null;
3009            }
3010                } else {
3011                    return null;
3012                }
3013            }
3014
3015            public Point getLocation() {
3016                if (parent != null) {
3017                    return parent.indexToLocation(indexInParent);
3018                } else {
3019                    return null;
3020                }
3021            }
3022
3023            public void setLocation(Point p) {
3024                if ((parent != null) && (parent.contains(p))) {
3025                    ensureIndexIsVisible(indexInParent);
3026                }
3027            }
3028
3029            public Rectangle getBounds() {
3030                if (parent != null) {
3031                    return parent.getCellBounds(indexInParent,indexInParent);
3032                } else {
3033                    return null;
3034                }
3035            }
3036
3037            public void setBounds(Rectangle r) {
3038                AccessibleContext ac = getCurrentAccessibleContext();
3039                if (ac instanceof AccessibleComponent) {
3040                    ((AccessibleComponent) ac).setBounds(r);
3041                }
3042            }
3043
3044            public Dimension getSize() {
3045                Rectangle cellBounds = this.getBounds();
3046                if (cellBounds != null) {
3047                    return cellBounds.getSize();
3048                } else {
3049                    return null;
3050                }
3051            }
3052
3053            public void setSize (Dimension d) {
3054                AccessibleContext ac = getCurrentAccessibleContext();
3055                if (ac instanceof AccessibleComponent) {
3056                    ((AccessibleComponent) ac).setSize(d);
3057                } else {
3058                    Component c = getCurrentComponent();
3059                    if (c != null) {
3060                        c.setSize(d);
3061                    }
3062                }
3063            }
3064
3065            public Accessible getAccessibleAt(Point p) {
3066                AccessibleContext ac = getCurrentAccessibleContext();
3067                if (ac instanceof AccessibleComponent) {
3068                    return ((AccessibleComponent) ac).getAccessibleAt(p);
3069                } else {
3070                    return null;
3071                }
3072            }
3073
3074            public boolean isFocusTraversable() {
3075                AccessibleContext ac = getCurrentAccessibleContext();
3076                if (ac instanceof AccessibleComponent) {
3077                    return ((AccessibleComponent) ac).isFocusTraversable();
3078                } else {
3079                    Component c = getCurrentComponent();
3080                    if (c != null) {
3081                        return c.isFocusTraversable();
3082                    } else {
3083                        return false;
3084                    }
3085                }
3086            }
3087
3088            public void requestFocus() {
3089                AccessibleContext ac = getCurrentAccessibleContext();
3090                if (ac instanceof AccessibleComponent) {
3091                    ((AccessibleComponent) ac).requestFocus();
3092                } else {
3093                    Component c = getCurrentComponent();
3094                    if (c != null) {
3095                        c.requestFocus();
3096                    }
3097                }
3098            }
3099
3100            public void addFocusListener(FocusListener l) {
3101                AccessibleContext ac = getCurrentAccessibleContext();
3102                if (ac instanceof AccessibleComponent) {
3103                    ((AccessibleComponent) ac).addFocusListener(l);
3104                } else {
3105                    Component c = getCurrentComponent();
3106                    if (c != null) {
3107                        c.addFocusListener(l);
3108                    }
3109                }
3110            }
3111
3112            public void removeFocusListener(FocusListener l) {
3113                AccessibleContext ac = getCurrentAccessibleContext();
3114                if (ac instanceof AccessibleComponent) {
3115                    ((AccessibleComponent) ac).removeFocusListener(l);
3116                } else {
3117                    Component c = getCurrentComponent();
3118                    if (c != null) {
3119                        c.removeFocusListener(l);
3120                    }
3121                }
3122            }
3123
3124            // TIGER - 4733624
3125
/**
3126             * Returns an AccessibleIcon
3127             *
3128             * @return the AccessibleIcon for the element renderer.
3129             */

3130            public AccessibleIcon [] getAccessibleIcon() {
3131                AccessibleContext ac = getCurrentAccessibleContext();
3132                if (ac != null) {
3133                    return ac.getAccessibleIcon();
3134                } else {
3135                    return null;
3136                }
3137            }
3138        } // inner class AccessibleJListChild
3139
} // inner class AccessibleJList
3140
}
3141
3142
Popular Tags