OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [javax/] [swing/] [JList.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* JList.java --
2
   Copyright (C) 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing;
40
 
41
import java.awt.Color;
42
import java.awt.Component;
43
import java.awt.ComponentOrientation;
44
import java.awt.Cursor;
45
import java.awt.Dimension;
46
import java.awt.Font;
47
import java.awt.FontMetrics;
48
import java.awt.Point;
49
import java.awt.Rectangle;
50
import java.awt.event.FocusListener;
51
import java.beans.PropertyChangeEvent;
52
import java.beans.PropertyChangeListener;
53
import java.util.Locale;
54
import java.util.Vector;
55
 
56
import javax.accessibility.Accessible;
57
import javax.accessibility.AccessibleComponent;
58
import javax.accessibility.AccessibleContext;
59
import javax.accessibility.AccessibleRole;
60
import javax.accessibility.AccessibleSelection;
61
import javax.accessibility.AccessibleState;
62
import javax.accessibility.AccessibleStateSet;
63
import javax.swing.event.ListDataEvent;
64
import javax.swing.event.ListDataListener;
65
import javax.swing.event.ListSelectionEvent;
66
import javax.swing.event.ListSelectionListener;
67
import javax.swing.plaf.ListUI;
68
import javax.swing.text.Position;
69
 
70
/**
71
 * <p>This class is a facade over three separate objects: {@link
72
 * javax.swing.ListModel}, {@link javax.swing.ListSelectionModel} and
73
 * {@link javax.swing.plaf.ListUI}. The facade represents a unified "list"
74
 * concept, with independently replacable (possibly client-provided) models
75
 * for its contents and its current selection. In addition, each element in
76
 * the list is rendered via a strategy class {@link
77
 * javax.swing.ListCellRenderer}.</p>
78
 *
79
 * <p>Lists have many properties, some of which are stored in this class
80
 * while others are delegated to the list's model or selection. The
81
 * following properties are available:</p>
82
 *
83
 * <table>
84
 * <tr><th>Property                       </th><th>Stored in</th><th>Bound?</th></tr>
85
 * <tr><td>accessibleContext              </td><td>list     </td><td>no    </td></tr>
86
 * <tr><td>anchorSelectionIndex           </td><td>selection</td><td>no    </td></tr>
87
 * <tr><td>cellRenderer                   </td><td>list     </td><td>yes   </td></tr>
88
 * <tr><td>dragEnabled                    </td><td>list     </td><td>no    </td></tr>
89
 * <tr><td>firstVisibleIndex              </td><td>list     </td><td>no    </td></tr>
90
 * <tr><td>fixedCellHeight                </td><td>list     </td><td>yes   </td></tr>
91
 * <tr><td>fixedCellWidth                 </td><td>list     </td><td>yes   </td></tr>
92
 * <tr><td>lastVisibleIndex               </td><td>list     </td><td>no    </td></tr>
93
 * <tr><td>layoutOrientation              </td><td>list     </td><td>yes   </td></tr>
94
 * <tr><td>leadSelectionIndex             </td><td>selection</td><td>no    </td></tr>
95
 * <tr><td>maxSelectionIndex              </td><td>selection</td><td>no    </td></tr>
96
 * <tr><td>minSelectionIndex              </td><td>selection</td><td>no    </td></tr>
97
 * <tr><td>model                          </td><td>list     </td><td>yes   </td></tr>
98
 * <tr><td>opaque                         </td><td>list     </td><td>no    </td></tr>
99
 * <tr><td>preferredScrollableViewportSize</td><td>list     </td><td>no    </td></tr>
100
 * <tr><td>prototypeCellValue             </td><td>list     </td><td>yes   </td></tr>
101
 * <tr><td>scrollableTracksViewportHeight </td><td>list     </td><td>no    </td></tr>
102
 * <tr><td>scrollableTracksViewportWidth  </td><td>list     </td><td>no    </td></tr>
103
 * <tr><td>selectedIndex                  </td><td>selection</td><td>no    </td></tr>
104
 * <tr><td>selectedIndices                </td><td>selection</td><td>no    </td></tr>
105
 * <tr><td>selectedValue                  </td><td>model    </td><td>no    </td></tr>
106
 * <tr><td>selectedValues                 </td><td>model    </td><td>no    </td></tr>
107
 * <tr><td>selectionBackground            </td><td>list     </td><td>yes   </td></tr>
108
 * <tr><td>selectionEmpty                 </td><td>selection</td><td>no    </td></tr>
109
 * <tr><td>selectionForeground            </td><td>list     </td><td>yes   </td></tr>
110
 * <tr><td>selectionMode                  </td><td>selection</td><td>no    </td></tr>
111
 * <tr><td>selectionModel                 </td><td>list     </td><td>yes   </td></tr>
112
 * <tr><td>UI                             </td><td>list     </td><td>yes   </td></tr>
113
 * <tr><td>UIClassID                      </td><td>list     </td><td>no    </td></tr>
114
 * <tr><td>valueIsAdjusting               </td><td>list     </td><td>no    </td></tr>
115
 * <tr><td>visibleRowCount                </td><td>list     </td><td>no    </td></tr>
116
 * </table>
117
 *
118
 * @author Graydon Hoare (graydon@redhat.com)
119
 */
120
 
121
public class JList extends JComponent implements Accessible, Scrollable
122
{
123
 
124
  /**
125
   * Provides accessibility support for <code>JList</code>.
126
   */
127
  protected class AccessibleJList extends AccessibleJComponent
128
    implements AccessibleSelection, PropertyChangeListener,
129
               ListSelectionListener, ListDataListener
130
  {
131
 
132
    /**
133
     * Provides accessibility support for list elements in <code>JList</code>s.
134
     */
135
    protected class AccessibleJListChild extends AccessibleContext
136
      implements Accessible, AccessibleComponent
137
    {
138
 
139
      /**
140
       * The parent list.
141
       */
142
      JList parent;
143
 
144
      /**
145
       * The index in the list for that child.
146
       */
147
      int listIndex;
148
 
149
      /**
150
       * The cursor for this list child.
151
       */
152
      // TODO: Testcases show that this class somehow stores state about the
153
      // cursor. I cannot make up though how that could affect
154
      // the actual list.
155
      Cursor cursor = Cursor.getDefaultCursor();
156
 
157
      /**
158
       * Creates a new instance of <code>AccessibleJListChild</code>.
159
       *
160
       * @param list the list of which this is an accessible child
161
       * @param index the list index for this child
162
       */
163
      public AccessibleJListChild(JList list, int index)
164
      {
165
        parent = list;
166
        listIndex = index;
167
      }
168
 
169
      /**
170
       * Returns the accessible context of this object. Returns
171
       * <code>this</code> since <code>AccessibleJListChild</code>s are their
172
       * own accessible contexts.
173
       *
174
       * @return the accessible context of this object, <code>this</code>
175
       */
176
      public AccessibleContext getAccessibleContext()
177
      {
178
        return this;
179
      }
180
 
181
      /**
182
       * Returns the background color for this list child. This returns the
183
       * background of the <code>JList</code> itself since the background
184
       * cannot be set on list children individually
185
       *
186
       * @return the background color for this list child
187
       */
188
      public Color getBackground()
189
      {
190
        return parent.getBackground();
191
      }
192
 
193
      /**
194
       * Calling this method has no effect, since the background color cannot be
195
       * set on list children individually.
196
       *
197
       * @param color not used here.
198
       */
199
      public void setBackground(Color color)
200
      {
201
        // Calling this method has no effect, since the background color cannot
202
        // be set on list children individually.
203
      }
204
 
205
      /**
206
       * Returns the foreground color for this list child. This returns the
207
       * background of the <code>JList</code> itself since the foreground
208
       * cannot be set on list children individually.
209
       *
210
       * @return the background color for this list child
211
       */
212
      public Color getForeground()
213
      {
214
        return parent.getForeground();
215
      }
216
 
217
      /**
218
       * Calling this method has no effect, since the foreground color cannot be
219
       * set on list children individually.
220
       *
221
       * @param color not used here.
222
       */
223
      public void setForeground(Color color)
224
      {
225
        // Calling this method has no effect, since the foreground color cannot
226
        // be set on list children individually.
227
      }
228
 
229
      /**
230
       * Returns the cursor for this list child.
231
       *
232
       * @return the cursor for this list child
233
       */
234
      public Cursor getCursor()
235
      {
236
        // TODO: Testcases show that this method returns the cursor that has
237
        // been set by setCursor. I cannot make up though how that could affect
238
        // the actual list.
239
        return cursor;
240
      }
241
 
242
      /**
243
       * Sets the cursor for this list child.
244
       */
245
      public void setCursor(Cursor cursor)
246
      {
247
        this.cursor = cursor;
248
        // TODO: Testcases show that this method returns the cursor that has
249
        // been set by setCursor. I cannot make up though how that could affect
250
        // the actual list.
251
      }
252
 
253
      /**
254
       * Returns the font of the <code>JList</code> since it is not possible to
255
       * set fonts for list children individually.
256
       *
257
       * @return the font of the <code>JList</code>
258
       */
259
      public Font getFont()
260
      {
261
        return parent.getFont();
262
      }
263
 
264
      /**
265
       * Does nothing since it is not possible to set the font on list children
266
       * individually.
267
       *
268
       * @param font not used here
269
       */
270
      public void setFont(Font font)
271
      {
272
        // Does nothing since it is not possible to set the font on list
273
        // children individually.
274
      }
275
 
276
      /**
277
       * Returns the font metrics for the specified font. This method forwards
278
       * to the parent <code>JList</code>.
279
       *
280
       * @param font the font for which the font metrics is queried
281
       *
282
       * @return the font metrics for the specified font
283
       */
284
      public FontMetrics getFontMetrics(Font font)
285
      {
286
        return parent.getFontMetrics(font);
287
      }
288
 
289
      /**
290
       * Returns <code>true</code> if the parent <code>JList</code> is enabled,
291
       * <code>false</code> otherwise. The list children cannot have an enabled
292
       * flag set individually.
293
       *
294
       * @return <code>true</code> if the parent <code>JList</code> is enabled,
295
       *         <code>false</code> otherwise
296
       */
297
      public boolean isEnabled()
298
      {
299
        return parent.isEnabled();
300
      }
301
 
302
      /**
303
       * Does nothing since the enabled flag cannot be set for list children
304
       * individually.
305
       *
306
       * @param b not used here
307
       */
308
      public void setEnabled(boolean b)
309
      {
310
        // Does nothing since the enabled flag cannot be set for list children
311
        // individually.
312
      }
313
 
314
      /**
315
       * Returns <code>true</code> if this list child is visible,
316
       * <code>false</code> otherwise. The value of this property depends
317
       * on {@link JList#getFirstVisibleIndex()} and
318
       * {@link JList#getLastVisibleIndex()}.
319
       *
320
       * @return <code>true</code> if this list child is visible,
321
       *         <code>false</code> otherwise
322
       */
323
      public boolean isVisible()
324
      {
325
        return listIndex >= parent.getFirstVisibleIndex()
326
               && listIndex <= parent.getLastVisibleIndex();
327
      }
328
 
329
      /**
330
       * The value of the visible property cannot be modified, so this method
331
       * does nothing.
332
       *
333
       * @param b not used here
334
       */
335
      public void setVisible(boolean b)
336
      {
337
        // The value of the visible property cannot be modified, so this method
338
        // does nothing.
339
      }
340
 
341
      /**
342
       * Returns <code>true</code> if this list child is currently showing on
343
       * screen and <code>false</code> otherwise. The list child is showing if
344
       * it is visible and if it's parent JList is currently showing.
345
       *
346
       * @return <code>true</code> if this list child is currently showing on
347
       *         screen and <code>false</code> otherwise
348
       */
349
      public boolean isShowing()
350
      {
351
        return isVisible() && parent.isShowing();
352
      }
353
 
354
      /**
355
       * Returns <code>true</code> if this list child covers the screen location
356
       * <code>point</code> (relative to the <code>JList</code> coordinate
357
       * system, <code>false</code> otherwise.
358
       *
359
       * @return <code>true</code> if this list child covers the screen location
360
       *         <code>point</code> , <code>false</code> otherwise
361
       */
362
      public boolean contains(Point point)
363
      {
364
        return getBounds().contains(point);
365
      }
366
 
367
      /**
368
       * Returns the absolute screen location of this list child.
369
       *
370
       * @return the absolute screen location of this list child
371
       */
372
      public Point getLocationOnScreen()
373
      {
374
        Point loc = getLocation();
375
        SwingUtilities.convertPointToScreen(loc, parent);
376
        return loc;
377
      }
378
 
379
      /**
380
       * Returns the screen location of this list child relative to it's parent.
381
       *
382
       * @return the location of this list child relative to it's parent
383
       *
384
       * @see JList#indexToLocation(int)
385
       */
386
      public Point getLocation()
387
      {
388
        return parent.indexToLocation(listIndex);
389
      }
390
 
391
      /**
392
       * Does nothing since the screen location cannot be set on list children
393
       * explictitly.
394
       *
395
       * @param point not used here
396
       */
397
      public void setLocation(Point point)
398
      {
399
        // Does nothing since the screen location cannot be set on list children
400
        // explictitly.
401
      }
402
 
403
      /**
404
       * Returns the bounds of this list child.
405
       *
406
       * @return the bounds of this list child
407
       *
408
       * @see JList#getCellBounds(int, int)
409
       */
410
      public Rectangle getBounds()
411
      {
412
        return parent.getCellBounds(listIndex, listIndex);
413
      }
414
 
415
      /**
416
       * Does nothing since the bounds cannot be set on list children
417
       * individually.
418
       *
419
       * @param rectangle not used here
420
       */
421
      public void setBounds(Rectangle rectangle)
422
      {
423
        // Does nothing since the bounds cannot be set on list children
424
        // individually.
425
      }
426
 
427
      /**
428
       * Returns the size of this list child.
429
       *
430
       * @return the size of this list child
431
       */
432
      public Dimension getSize()
433
      {
434
        Rectangle b = getBounds();
435
        return b.getSize();
436
      }
437
 
438
      /**
439
       * Does nothing since the size cannot be set on list children
440
       * individually.
441
       *
442
       * @param dimension not used here
443
       */
444
      public void setSize(Dimension dimension)
445
      {
446
        // Does nothing since the size cannot be set on list children
447
        // individually.
448
      }
449
 
450
      /**
451
       * Returns <code>null</code> because list children do not have children
452
       * themselves
453
       *
454
       * @return <code>null</code>
455
       */
456
      public Accessible getAccessibleAt(Point point)
457
      {
458
        return null;
459
      }
460
 
461
      /**
462
       * Returns <code>true</code> since list children are focus traversable.
463
       *
464
       * @return true
465
       */
466
      public boolean isFocusTraversable()
467
      {
468
        // TODO: Is this 100% ok?
469
        return true;
470
      }
471
 
472
      /**
473
       * Requests focus on the parent list. List children cannot request focus
474
       * individually.
475
       */
476
      public void requestFocus()
477
      {
478
        // TODO: Is this 100% ok?
479
        parent.requestFocus();
480
      }
481
 
482
      /**
483
       * Adds a focus listener to the parent list. List children do not have
484
       * their own focus management.
485
       *
486
       * @param listener the focus listener to add
487
       */
488
      public void addFocusListener(FocusListener listener)
489
      {
490
        // TODO: Is this 100% ok?
491
        parent.addFocusListener(listener);
492
      }
493
 
494
      /**
495
       * Removes a focus listener from the parent list. List children do not
496
       * have their own focus management.
497
       *
498
       * @param listener the focus listener to remove
499
       */
500
      public void removeFocusListener(FocusListener listener)
501
      {
502
        // TODO: Is this 100%
503
        parent.removeFocusListener(listener);
504
      }
505
 
506
      /**
507
       * Returns the accessible role of this list item, which is
508
       * {@link AccessibleRole#LABEL}.
509
       *
510
       * @return {@link AccessibleRole#LABEL}
511
       */
512
      public AccessibleRole getAccessibleRole()
513
      {
514
        return AccessibleRole.LABEL;
515
      }
516
 
517
      /**
518
       * Returns the accessible state set of this list item.
519
       *
520
       * @return the accessible state set of this list item
521
       */
522
      public AccessibleStateSet getAccessibleStateSet()
523
      {
524
        AccessibleStateSet states = new AccessibleStateSet();
525
        if (isVisible())
526
          states.add(AccessibleState.VISIBLE);
527
        if (isShowing())
528
          states.add(AccessibleState.SHOWING);
529
        if (isFocusTraversable())
530
          states.add(AccessibleState.FOCUSABLE);
531
        // TODO: How should the active state be handled? The API docs
532
        // suggest that this state is set on the activated list child,
533
        // that is the one that is drawn with a box. However, I don't know how
534
        // to implement this.
535
 
536
        // TODO: We set the selectable state here because list children are
537
        // selectable. Is there a way to disable single children?
538
        if (parent.isEnabled())
539
          states.add(AccessibleState.SELECTABLE);
540
 
541
        if (parent.isSelectedIndex(listIndex))
542
          states.add(AccessibleState.SELECTED);
543
 
544
        // TODO: Handle more states here?
545
        return states;
546
      }
547
 
548
      /**
549
       * Returns the index of this list child within it's parent list.
550
       *
551
       * @return the index of this list child within it's parent list
552
       */
553
      public int getAccessibleIndexInParent()
554
      {
555
        return listIndex;
556
      }
557
 
558
      /**
559
       * Returns <code>0</code> since list children don't have children
560
       * themselves.
561
       *
562
       * @return <code>0</code>
563
       */
564
      public int getAccessibleChildrenCount()
565
      {
566
        return 0;
567
      }
568
 
569
      /**
570
       * Returns <code>null</code> since list children don't have children
571
       * themselves.
572
       *
573
       * @return <code>null</code>
574
       */
575
      public Accessible getAccessibleChild(int i)
576
      {
577
        return null;
578
      }
579
 
580
      /**
581
       * Returns the locale of this component. This call is forwarded to the
582
       * parent list since list children don't have a separate locale setting.
583
       *
584
       * @return the locale of this component
585
       */
586
      public Locale getLocale()
587
      {
588
        return parent.getLocale();
589
      }
590
 
591
      /**
592
       * This method does
593
       * nothing, list children are transient accessible objects which means
594
       * that they don't fire property change events.
595
       *
596
       * @param l not used here
597
       */
598
      public void addPropertyChangeListener(PropertyChangeListener l)
599
      {
600
        // Do nothing here.
601
      }
602
 
603
      /**
604
       * This method does
605
       * nothing, list children are transient accessible objects which means
606
       * that they don't fire property change events.
607
       *
608
       * @param l not used here
609
       */
610
      public void removePropertyChangeListener(PropertyChangeListener l)
611
      {
612
        // Do nothing here.
613
      }
614
 
615
      // TODO: Implement the remaining methods of this class.
616
    }
617
 
618
    /**
619
     * Create a new AccessibleJList.
620
     */
621
    public AccessibleJList()
622
    {
623
      // Nothing to do here.
624
    }
625
 
626
    /**
627
     * Returns the number of selected accessible children.
628
     *
629
     * @return the number of selected accessible children
630
     */
631
    public int getAccessibleSelectionCount()
632
    {
633
      return getSelectedIndices().length;
634
    }
635
 
636
    /**
637
     * Returns the n-th selected accessible child.
638
     *
639
     * @param n the index of the selected child to return
640
     *
641
     * @return the n-th selected accessible child
642
     */
643
    public Accessible getAccessibleSelection(int n)
644
    {
645
      return new AccessibleJListChild(JList.this, getSelectedIndices()[n]);
646
    }
647
 
648
    /**
649
     * Returns <code>true</code> if the n-th child is selected,
650
     * <code>false</code> otherwise.
651
     *
652
     * @param n the index of the child of which the selected state is queried
653
     *
654
     * @return <code>true</code> if the n-th child is selected,
655
     *         <code>false</code> otherwise
656
     */
657
    public boolean isAccessibleChildSelected(int n)
658
    {
659
      return isSelectedIndex(n);
660
    }
661
 
662
    /**
663
     * Adds the accessible item with the specified index to the selected items.
664
     * If multiple selections are supported, the item is added to the selection,
665
     * otherwise the item replaces the current selection.
666
     *
667
     * @param i the index of the item to add to the selection
668
     */
669
    public void addAccessibleSelection(int i)
670
    {
671
      addSelectionInterval(i, i);
672
    }
673
 
674
    /**
675
     * Removes the accessible item with the specified index to the selection.
676
     *
677
     * @param i the index of the item to be removed from the selection
678
     */
679
    public void removeAccessibleSelection(int i)
680
    {
681
      removeSelectionInterval(i, i);
682
    }
683
 
684
    /**
685
     * Remove all selection items from the selection.
686
     */
687
    public void clearAccessibleSelection()
688
    {
689
      clearSelection();
690
    }
691
 
692
    /**
693
     * Selects all items if multiple selections are supported.
694
     * Otherwise do nothing.
695
     */
696
    public void selectAllAccessibleSelection()
697
    {
698
      addSelectionInterval(0, getModel().getSize());
699
    }
700
 
701
    /**
702
     * Receices notification when the list selection is changed. This method
703
     * fires two property change events, the first with
704
     * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY} and the second
705
     * with {@link AccessibleContext#ACCESSIBLE_SELECTION_PROPERTY}.
706
     *
707
     * @param event the list selection event
708
     */
709
    public void valueChanged(ListSelectionEvent event)
710
    {
711
      firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
712
                         Boolean.TRUE);
713
      firePropertyChange(ACCESSIBLE_SELECTION_PROPERTY, Boolean.FALSE,
714
                         Boolean.TRUE);
715
    }
716
 
717
    /**
718
     * Receives notification when items have changed in the
719
     * <code>JList</code>. This method fires a property change event with
720
     * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY}.
721
     *
722
     * @param event the list data event
723
     */
724
    public void contentsChanged(ListDataEvent event)
725
    {
726
      firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
727
                         Boolean.TRUE);
728
    }
729
 
730
    /**
731
     * Receives notification when items are inserted into the
732
     * <code>JList</code>. This method fires a property change event with
733
     * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY}.
734
     *
735
     * @param event the list data event
736
     */
737
    public void intervalAdded(ListDataEvent event)
738
    {
739
      firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
740
                         Boolean.TRUE);
741
    }
742
 
743
    /**
744
     * Receives notification when items are removed from the
745
     * <code>JList</code>. This method fires a property change event with
746
     * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY}.
747
     *
748
     * @param event the list data event
749
     */
750
    public void intervalRemoved(ListDataEvent event)
751
    {
752
      firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
753
                         Boolean.TRUE);
754
    }
755
 
756
 
757
    /**
758
     * Receives notification about changes of the <code>JList</code>'s
759
     * properties. This is used to re-register this object as listener to
760
     * the data model and selection model when the data model or selection model
761
     * changes.
762
     *
763
     * @param e the property change event
764
     */
765
    public void propertyChange(PropertyChangeEvent e)
766
    {
767
      String propertyName = e.getPropertyName();
768
      if (propertyName.equals("model"))
769
        {
770
          ListModel oldModel = (ListModel) e.getOldValue();
771
          oldModel.removeListDataListener(this);
772
          ListModel newModel = (ListModel) e.getNewValue();
773
          newModel.addListDataListener(this);
774
        }
775
      else if (propertyName.equals("selectionModel"))
776
        {
777
          ListSelectionModel oldModel = (ListSelectionModel) e.getOldValue();
778
          oldModel.removeListSelectionListener(this);
779
          ListSelectionModel newModel = (ListSelectionModel) e.getNewValue();
780
          oldModel.addListSelectionListener(this);
781
        }
782
    }
783
 
784
    /**
785
     * Return the state set of the <code>JList</code>.
786
     *
787
     * @return the state set of the <code>JList</code>
788
     */
789
    public AccessibleStateSet getAccessibleStateSet()
790
    {
791
      // TODO: Figure out if there is possibly more state that must be
792
      // handled here.
793
      AccessibleStateSet s = super.getAccessibleStateSet();
794
      if (getSelectionMode() != ListSelectionModel.SINGLE_SELECTION)
795
        s.add(AccessibleState.MULTISELECTABLE);
796
      return s;
797
    }
798
 
799
    /**
800
     * Returns the accessible role for <code>JList</code>,
801
     * {@link AccessibleRole#LIST}.
802
     *
803
     * @return the accessible role for <code>JList</code>
804
     */
805
    public AccessibleRole getAccessibleRole()
806
    {
807
      return AccessibleRole.LIST;
808
    }
809
 
810
    /**
811
     * Returns the accessible child at the visual location <code>p</code>
812
     * (relative to the upper left corner of the <code>JList</code>). If there
813
     * is no child at that location, this returns <code>null</code>.
814
     *
815
     * @param p the screen location for which to return the accessible child
816
     *
817
     * @return the accessible child at the specified location, or
818
     *         <code>null</code> if there is no child at that location
819
     */
820
    public Accessible getAccessibleAt(Point p)
821
    {
822
      int childIndex = locationToIndex(p);
823
      return getAccessibleChild(childIndex);
824
    }
825
 
826
    /**
827
     * Returns the number of accessible children in the <code>JList</code>.
828
     *
829
     * @return the number of accessible children in the <code>JList</code>
830
     */
831
    public int getAccessibleChildrenCount()
832
    {
833
      return getModel().getSize();
834
    }
835
 
836
    /**
837
     * Returns the n-th accessible child of this <code>JList</code>. This will
838
     * be an instance of {@link AccessibleJListChild}. If there is no child
839
     * at that index, <code>null</code> is returned.
840
     *
841
     * @param n the index of the child to return
842
     *
843
     * @return the n-th accessible child of this <code>JList</code>
844
     */
845
    public Accessible getAccessibleChild(int n)
846
    {
847
      if (getModel().getSize() <= n)
848
        return null;
849
      return new AccessibleJListChild(JList.this, n);
850
    }
851
  }
852
 
853
  private static final long serialVersionUID = 4406629526391098046L;
854
 
855
  /**
856
   * Constant value used in "layoutOrientation" property. This value means
857
   * that cells are laid out in a single vertical column. This is the default.
858
   */
859
  public static final int VERTICAL = 0;
860
 
861
  /**
862
   * Constant value used in "layoutOrientation" property. This value means
863
   * that cells are laid out in multiple columns "newspaper style", filling
864
   * vertically first, then horizontally.
865
   */
866
  public static final int VERTICAL_WRAP = 1;
867
 
868
  /**
869
   * Constant value used in "layoutOrientation" property. This value means
870
   * that cells are laid out in multiple columns "newspaper style",
871
   * filling horizontally first, then vertically.
872
   */
873
  public static final int HORIZONTAL_WRAP = 2;
874
 
875
  /**
876
   * This property indicates whether "drag and drop" functions are enabled
877
   * on the list.
878
   */
879
  boolean dragEnabled;
880
 
881
  /** This property provides a strategy for rendering cells in the list. */
882
  ListCellRenderer cellRenderer;
883
 
884
  /**
885
   * This property indicates an fixed width to assign to all cells in the
886
   * list. If its value is <code>-1</code>, no width has been
887
   * assigned. This value can be set explicitly, or implicitly by setting
888
   * the {@link #prototypeCellValue} property.
889
   */
890
  int fixedCellWidth;
891
 
892
  /**
893
   * This property indicates an fixed height to assign to all cells in the
894
   * list. If its value is <code>-1</code>, no height has been
895
   * assigned. This value can be set explicitly, or implicitly by setting
896
   * the {@link #prototypeCellValue} property.
897
   */
898
  int fixedCellHeight;
899
 
900
  /**
901
   * This property holds the current layout orientation of the list, which
902
   * is one of the integer constants {@link #VERTICAL}, {@link
903
   * #VERTICAL_WRAP}, or {@link #HORIZONTAL_WRAP}.
904
   */
905
  int layoutOrientation;
906
 
907
  /** This property holds the data elements displayed by the list. */
908
  ListModel model;
909
 
910
  /**
911
   * <p>This property holds a reference to a "prototype" data value --
912
   * typically a String -- which is used to calculate the {@link
913
   * #fixedCellWidth} and {@link #fixedCellHeight} properties, using the
914
   * {@link #cellRenderer} property to acquire a component to render the
915
   * prototype.</p>
916
   *
917
   * <p>It is important that you <em>not</em> set this value to a
918
   * component. It has to be a <em>data value</em> such as the objects you
919
   * would find in the list's model. Setting it to a component will have
920
   * undefined (and undesirable) affects. </p>
921
   */
922
  Object prototypeCellValue;
923
 
924
  /**
925
   * This property specifies a foreground color for the selected cells in
926
   * the list. When {@link ListCellRenderer#getListCellRendererComponent}
927
   * is called with a selected cell object, the component returned will
928
   * have its "foreground" set to this color.
929
   */
930
  Color selectionBackground;
931
 
932
  /**
933
   * This property specifies a background color for the selected cells in
934
   * the list. When {@link ListCellRenderer#getListCellRendererComponent}
935
   * is called with a selected cell object, the component returned will
936
   * have its "background" property set to this color.
937
   */
938
  Color selectionForeground;
939
 
940
  /**
941
   * This property holds a description of which data elements in the {@link
942
   * #model} property should be considered "selected", when displaying and
943
   * interacting with the list.
944
   */
945
  ListSelectionModel selectionModel;
946
 
947
 
948
  /**
949
   * This property indicates that the list's selection is currently
950
   * "adjusting" -- perhaps due to a user actively dragging the mouse over
951
   * multiple list elements -- and is therefore likely to change again in
952
   * the near future. A {@link ListSelectionListener} might choose to delay
953
   * updating its view of the list's selection until this property is
954
   * false, meaning that the adjustment has completed.
955
   */
956
  boolean valueIsAdjusting;
957
 
958
  /**
959
   * This property indicates a <em>preference</em> for the number of rows
960
   * displayed in the list, and will scale the
961
   * {@link #getPreferredScrollableViewportSize} property accordingly. The actual
962
   * number of displayed rows, when the list is placed in a real {@link
963
   * JViewport} or other component, may be greater or less than this number.
964
   */
965
  int visibleRowCount;
966
 
967
  /**
968
   * Fire a {@link ListSelectionEvent} to all the registered ListSelectionListeners.
969
   */
970
  protected void fireSelectionValueChanged(int firstIndex, int lastIndex, boolean isAdjusting)
971
  {
972
    ListSelectionEvent evt = new ListSelectionEvent(this, firstIndex, lastIndex, isAdjusting);
973
    ListSelectionListener listeners[] = getListSelectionListeners();
974
    for (int i = 0; i < listeners.length; ++i)
975
      {
976
        listeners[i].valueChanged(evt);
977
      }
978
  }
979
 
980
  /**
981
   * This private listener propagates {@link ListSelectionEvent} events
982
   * from the list's "selectionModel" property to the list's {@link
983
   * ListSelectionListener} listeners. It also listens to {@link
984
   * ListDataEvent} events from the list's {@link #model} property. If this
985
   * class receives either type of event, it triggers repainting of the
986
   * list.
987
   */
988
  private class ListListener
989
    implements ListSelectionListener, ListDataListener
990
  {
991
    // ListDataListener events
992
    public void contentsChanged(ListDataEvent event)
993
    {
994
      JList.this.revalidate();
995
      JList.this.repaint();
996
    }
997
    public void intervalAdded(ListDataEvent event)
998
    {
999
      JList.this.revalidate();
1000
      JList.this.repaint();
1001
    }
1002
    public void intervalRemoved(ListDataEvent event)
1003
    {
1004
      JList.this.revalidate();
1005
      JList.this.repaint();
1006
    }
1007
    // ListSelectionListener events
1008
    public void valueChanged(ListSelectionEvent event)
1009
    {
1010
      JList.this.fireSelectionValueChanged(event.getFirstIndex(),
1011
                                           event.getLastIndex(),
1012
                                           event.getValueIsAdjusting());
1013
      JList.this.repaint();
1014
    }
1015
  }
1016
 
1017
  /**
1018
   * Shared ListListener instance, subscribed to both the current {@link
1019
   * #model} and {@link #selectionModel} properties of the list.
1020
   */
1021
  ListListener listListener;
1022
 
1023
 
1024
  /**
1025
   * Creates a new JList object.
1026
   */
1027
  public JList()
1028
  {
1029
    init();
1030
  }
1031
 
1032
  /**
1033
   * Creates a new JList object.
1034
   *
1035
   * @param listData Initial data to populate the list with
1036
   */
1037
  public JList(Object[] listData)
1038
  {
1039
    init();
1040
    setListData(listData);
1041
  }
1042
 
1043
  /**
1044
   * Creates a new JList object.
1045
   *
1046
   * @param listData Initial data to populate the list with
1047
   */
1048
  public JList(Vector listData)
1049
  {
1050
    init();
1051
    setListData(listData);
1052
  }
1053
 
1054
  /**
1055
   * Creates a new JList object.
1056
   *
1057
   * @param listData Initial data to populate the list with
1058
   */
1059
  public JList(ListModel listData)
1060
  {
1061
    init();
1062
    setModel(listData);
1063
  }
1064
 
1065
  void init()
1066
  {
1067
    dragEnabled = false;
1068
    fixedCellHeight = -1;
1069
    fixedCellWidth = -1;
1070
    layoutOrientation = VERTICAL;
1071
    opaque = true;
1072
    valueIsAdjusting = false;
1073
    visibleRowCount = 8;
1074
 
1075
    cellRenderer = new DefaultListCellRenderer();
1076
    listListener = new ListListener();
1077
 
1078
    setModel(new DefaultListModel());
1079
    setSelectionModel(createSelectionModel());
1080
 
1081
    updateUI();
1082
  }
1083
 
1084
  /**
1085
   * Creates the default <code>ListSelectionModel</code>.
1086
   *
1087
   * @return the <code>ListSelectionModel</code>
1088
   */
1089
  protected ListSelectionModel createSelectionModel()
1090
  {
1091
    return new DefaultListSelectionModel();
1092
  }
1093
 
1094
  /**
1095
   * Gets the value of the {@link #fixedCellHeight} property. This property
1096
   * may be <code>-1</code> to indicate that no cell height has been
1097
   * set. This property is also set implicitly when the
1098
   * {@link #prototypeCellValue} property is set.
1099
   *
1100
   * @return The current value of the property
1101
   *
1102
   * @see #fixedCellHeight
1103
   * @see #setFixedCellHeight
1104
   * @see #setPrototypeCellValue
1105
   */
1106
  public int getFixedCellHeight()
1107
  {
1108
    return fixedCellHeight;
1109
  }
1110
 
1111
  /**
1112
   * Sets the value of the {@link #fixedCellHeight} property. This property
1113
   * may be <code>-1</code> to indicate that no cell height has been
1114
   * set. This property is also set implicitly when the {@link
1115
   * #prototypeCellValue} property is set, but setting it explicitly
1116
   * overrides the height computed from {@link #prototypeCellValue}.
1117
   *
1118
   * @see #getFixedCellHeight
1119
   * @see #getPrototypeCellValue
1120
   */
1121
  public void setFixedCellHeight(int h)
1122
  {
1123
    if (fixedCellHeight == h)
1124
      return;
1125
 
1126
    int old = fixedCellHeight;
1127
    fixedCellHeight = h;
1128
    firePropertyChange("fixedCellWidth", old, h);
1129
  }
1130
 
1131
 
1132
  /**
1133
   * Gets the value of the {@link #fixedCellWidth} property. This property
1134
   * may be <code>-1</code> to indicate that no cell width has been
1135
   * set. This property is also set implicitly when the {@link
1136
   * #prototypeCellValue} property is set.
1137
   *
1138
   * @return The current value of the property
1139
   *
1140
   * @see #setFixedCellWidth
1141
   * @see #setPrototypeCellValue
1142
   */
1143
  public int getFixedCellWidth()
1144
  {
1145
    return fixedCellWidth;
1146
  }
1147
 
1148
  /**
1149
   * Sets the value of the {@link #fixedCellWidth} property. This property
1150
   * may be <code>-1</code> to indicate that no cell width has been
1151
   * set. This property is also set implicitly when the {@link
1152
   * #prototypeCellValue} property is set, but setting it explicitly
1153
   * overrides the width computed from {@link #prototypeCellValue}.
1154
   *
1155
   * @see #getFixedCellHeight
1156
   * @see #getPrototypeCellValue
1157
   */
1158
  public void setFixedCellWidth(int w)
1159
  {
1160
    if (fixedCellWidth == w)
1161
      return;
1162
 
1163
    int old = fixedCellWidth;
1164
    fixedCellWidth = w;
1165
    firePropertyChange("fixedCellWidth", old, w);
1166
  }
1167
 
1168
  /**
1169
   * Gets the value of the {@link #visibleRowCount} property.
1170
   *
1171
   * @return the current value of the property.
1172
   */
1173
 
1174
  public int getVisibleRowCount()
1175
  {
1176
    return visibleRowCount;
1177
  }
1178
 
1179
  /**
1180
   * Sets the value of the {@link #visibleRowCount} property.
1181
   *
1182
   * @param vc The new property value
1183
   */
1184
  public void setVisibleRowCount(int vc)
1185
  {
1186
    visibleRowCount = vc;
1187
    revalidate();
1188
    repaint();
1189
  }
1190
 
1191
  /**
1192
   * Adds a {@link ListSelectionListener} to the listener list for this
1193
   * list. The listener will be called back with a {@link
1194
   * ListSelectionEvent} any time the list's {@link #selectionModel}
1195
   * property changes. The source of such events will be the JList,
1196
   * not the selection model.
1197
   *
1198
   * @param listener The new listener to add
1199
   */
1200
  public void addListSelectionListener(ListSelectionListener listener)
1201
  {
1202
    listenerList.add (ListSelectionListener.class, listener);
1203
  }
1204
 
1205
  /**
1206
   * Removes a {@link ListSelectionListener} from the listener list for
1207
   * this list. The listener will no longer be called when the list's
1208
   * {@link #selectionModel} changes.
1209
   *
1210
   * @param listener The listener to remove
1211
   */
1212
  public void removeListSelectionListener(ListSelectionListener listener)
1213
  {
1214
    listenerList.remove(ListSelectionListener.class, listener);
1215
  }
1216
 
1217
  /**
1218
   * Returns an array of all ListSelectionListeners subscribed to this
1219
   * list.
1220
   *
1221
   * @return The current subscribed listeners
1222
   *
1223
   * @since 1.4
1224
   */
1225
  public ListSelectionListener[] getListSelectionListeners()
1226
  {
1227
    return (ListSelectionListener[]) getListeners(ListSelectionListener.class);
1228
  }
1229
 
1230
  public int getSelectionMode()
1231
  {
1232
    return selectionModel.getSelectionMode();
1233
  }
1234
 
1235
  /**
1236
   * Sets the list's "selectionMode" property, which simply mirrors the
1237
   * same property on the list's {@link #selectionModel} property. This
1238
   * property should be one of the integer constants
1239
   * <code>SINGLE_SELECTION</code>, <code>SINGLE_INTERVAL_SELECTION</code>,
1240
   * or <code>MULTIPLE_INTERVAL_SELECTION</code> from the {@link
1241
   * ListSelectionModel} interface.
1242
   *
1243
   * @param a The new selection mode
1244
   */
1245
  public void setSelectionMode(int a)
1246
  {
1247
    selectionModel.setSelectionMode(a);
1248
  }
1249
 
1250
  /**
1251
   * Adds the interval <code>[a,a]</code> to the set of selections managed
1252
   * by this list's {@link #selectionModel} property. Depending on the
1253
   * selection mode, this may cause existing selections to become invalid,
1254
   * or may simply expand the set of selections.
1255
   *
1256
   * @param a A number in the half-open range <code>[0, x)</code> where
1257
   * <code>x = getModel.getSize()</code>, indicating the index of an
1258
   * element in the list to select.
1259
   *
1260
   * @see #setSelectionMode
1261
   * @see #selectionModel
1262
   */
1263
  public void setSelectedIndex(int a)
1264
  {
1265
    selectionModel.setSelectionInterval(a, a);
1266
  }
1267
 
1268
  /**
1269
   * For each element <code>a[i]</code> of the provided array
1270
   * <code>a</code>, calls {@link #setSelectedIndex} on <code>a[i]</code>.
1271
   *
1272
   * @see #setSelectionMode
1273
   * @see #selectionModel
1274
   */
1275
  public void setSelectedIndices(int [] a)
1276
  {
1277
    for (int i = 0; i < a.length; ++i)
1278
      setSelectedIndex(a[i]);
1279
  }
1280
 
1281
  /**
1282
   * Returns the minimum index of an element in the list which is currently
1283
   * selected.
1284
   *
1285
   * @return A number in the half-open range <code>[0, x)</code> where
1286
   * <code>x = getModel.getSize()</code>, indicating the minimum index of
1287
   * an element in the list for which the element is selected, or
1288
   * <code>-1</code> if no elements are selected
1289
   */
1290
  public int getSelectedIndex()
1291
  {
1292
    return selectionModel.getMinSelectionIndex();
1293
  }
1294
 
1295
  /**
1296
   * Returns <code>true</code> if the model's selection is empty, otherwise
1297
   * <code>false</code>.
1298
   *
1299
   * @return The return value of {@link ListSelectionModel#isSelectionEmpty}
1300
   */
1301
  public boolean isSelectionEmpty()
1302
  {
1303
    return selectionModel.isSelectionEmpty();
1304
  }
1305
 
1306
  /**
1307
   * Returns the list index of the upper left or upper right corner of the
1308
   * visible rectangle of this list, depending on the {@link
1309
   * Component#getComponentOrientation} property.
1310
   *
1311
   * @return The index of the first visible list cell, or <code>-1</code>
1312
   * if none is visible.
1313
   */
1314
  public int getFirstVisibleIndex()
1315
  {
1316
    ComponentOrientation or = getComponentOrientation();
1317
    Rectangle r = getVisibleRect();
1318
    if (or == ComponentOrientation.RIGHT_TO_LEFT)
1319
      r.translate((int) r.getWidth() - 1, 0);
1320
    return getUI().locationToIndex(this, r.getLocation());
1321
  }
1322
 
1323
 
1324
  /**
1325
   * Returns index of the cell to which specified location is closest to. If
1326
   * the location is outside the bounds of the list, then the greatest index
1327
   * in the list model is returned. If the list model is empty, then
1328
   * <code>-1</code> is returned.
1329
   *
1330
   * @param location for which to look for in the list
1331
   *
1332
   * @return index of the cell to which specified location is closest to.
1333
   */
1334
   public int locationToIndex(Point location)
1335
   {
1336
     return getUI().locationToIndex(this, location);
1337
   }
1338
 
1339
  /**
1340
   * Returns location of the cell located at the specified index in the list.
1341
   * @param index of the cell for which location will be determined
1342
   *
1343
   * @return location of the cell located at the specified index in the list.
1344
   */
1345
   public Point indexToLocation(int index)
1346
   {
1347
     return getUI().indexToLocation(this, index);
1348
   }
1349
 
1350
  /**
1351
   * Returns the list index of the lower right or lower left corner of the
1352
   * visible rectangle of this list, depending on the {@link
1353
   * Component#getComponentOrientation} property.
1354
   *
1355
   * @return The index of the last visible list cell, or <code>-1</code>
1356
   * if none is visible.
1357
   */
1358
  public int getLastVisibleIndex()
1359
  {
1360
    ComponentOrientation or = getComponentOrientation();
1361
    Rectangle r = getVisibleRect();
1362
    r.translate(0, (int) r.getHeight() - 1);
1363
    if (or == ComponentOrientation.LEFT_TO_RIGHT)
1364
      r.translate((int) r.getWidth() - 1, 0);
1365
    if (getUI().locationToIndex(this, r.getLocation()) == -1
1366
        && indexToLocation(getModel().getSize() - 1).y < r.y)
1367
      return getModel().getSize() - 1;
1368
    return getUI().locationToIndex(this, r.getLocation());
1369
  }
1370
 
1371
  /**
1372
   * Returns the indices of values in the {@link #model} property which are
1373
   * selected.
1374
   *
1375
   * @return An array of model indices, each of which is selected according
1376
   *         to the {@link #getSelectedValues} property
1377
   */
1378
  public int[] getSelectedIndices()
1379
  {
1380
    int lo, hi, n, i, j;
1381
    if (selectionModel.isSelectionEmpty())
1382
      return new int[0];
1383
    lo = selectionModel.getMinSelectionIndex();
1384
    hi = selectionModel.getMaxSelectionIndex();
1385
    n = 0;
1386
    for (i = lo; i <= hi; ++i)
1387
      if (selectionModel.isSelectedIndex(i))
1388
        n++;
1389
    int [] v = new int[n];
1390
    j = 0;
1391
    for (i = lo; i <= hi; ++i)
1392
      if (selectionModel.isSelectedIndex(i))
1393
        v[j++] = i;
1394
    return v;
1395
  }
1396
 
1397
  /**
1398
   * Indicates whether the list element at a given index value is
1399
   * currently selected.
1400
   *
1401
   * @param a The index to check
1402
   * @return <code>true</code> if <code>a</code> is the index of a selected
1403
   * list element
1404
   */
1405
  public boolean isSelectedIndex(int a)
1406
  {
1407
    return selectionModel.isSelectedIndex(a);
1408
  }
1409
 
1410
  /**
1411
   * Returns the first value in the list's {@link #model} property which is
1412
   * selected, according to the list's {@link #selectionModel} property.
1413
   * This is equivalent to calling
1414
   * <code>getModel()getElementAt(getSelectedIndex())</code>, with a check
1415
   * for the special index value of <code>-1</code> which returns null
1416
   * <code>null</code>.
1417
   *
1418
   * @return The first selected element, or <code>null</code> if no element
1419
   * is selected.
1420
   *
1421
   * @see #getSelectedValues
1422
   */
1423
  public Object getSelectedValue()
1424
  {
1425
    int index = getSelectedIndex();
1426
    if (index == -1)
1427
      return null;
1428
    return getModel().getElementAt(index);
1429
  }
1430
 
1431
  /**
1432
   * Returns all the values in the list's {@link #model} property which
1433
   * are selected, according to the list's {@link #selectionModel} property.
1434
   *
1435
   * @return An array containing all the selected values
1436
   *
1437
   * @see #setSelectedValue
1438
   */
1439
  public Object[] getSelectedValues()
1440
  {
1441
    int [] idx = getSelectedIndices();
1442
    Object [] v = new Object[idx.length];
1443
    for (int i = 0; i < idx.length; ++i)
1444
      v[i] = getModel().getElementAt(i);
1445
    return v;
1446
  }
1447
 
1448
  /**
1449
   * Gets the value of the {@link #selectionBackground} property.
1450
   *
1451
   * @return The current value of the property
1452
   */
1453
  public Color getSelectionBackground()
1454
  {
1455
    return selectionBackground;
1456
  }
1457
 
1458
  /**
1459
   * Sets the value of the {@link #selectionBackground} property.
1460
   *
1461
   * @param c The new value of the property
1462
   */
1463
  public void setSelectionBackground(Color c)
1464
  {
1465
    if (selectionBackground == c)
1466
      return;
1467
 
1468
    Color old = selectionBackground;
1469
    selectionBackground = c;
1470
    firePropertyChange("selectionBackground", old, c);
1471
    repaint();
1472
  }
1473
 
1474
  /**
1475
   * Gets the value of the {@link #selectionForeground} property.
1476
   *
1477
   * @return The current value of the property
1478
   */
1479
  public Color getSelectionForeground()
1480
  {
1481
    return selectionForeground;
1482
  }
1483
 
1484
  /**
1485
   * Sets the value of the {@link #selectionForeground} property.
1486
   *
1487
   * @param c The new value of the property
1488
   */
1489
  public void setSelectionForeground(Color c)
1490
  {
1491
    if (selectionForeground == c)
1492
      return;
1493
 
1494
    Color old = selectionForeground;
1495
    selectionForeground = c;
1496
    firePropertyChange("selectionForeground", old, c);
1497
  }
1498
 
1499
  /**
1500
   * Sets the selection to cover only the specified value, if it
1501
   * exists in the model.
1502
   *
1503
   * @param obj The object to select
1504
   * @param scroll Whether to scroll the list to make the newly selected
1505
   * value visible
1506
   *
1507
   * @see #ensureIndexIsVisible
1508
   */
1509
 
1510
  public void setSelectedValue(Object obj, boolean scroll)
1511
  {
1512
    for (int i = 0; i < model.getSize(); ++i)
1513
      {
1514
        if (model.getElementAt(i).equals(obj))
1515
          {
1516
            setSelectedIndex(i);
1517
            if (scroll)
1518
              ensureIndexIsVisible(i);
1519
            break;
1520
          }
1521
      }
1522
  }
1523
 
1524
  /**
1525
   * Scrolls this list to make the specified cell visible. This
1526
   * only works if the list is contained within a viewport.
1527
   *
1528
   * @param i The list index to make visible
1529
   *
1530
   * @see JComponent#scrollRectToVisible
1531
   */
1532
  public void ensureIndexIsVisible(int i)
1533
  {
1534
    scrollRectToVisible(getUI().getCellBounds(this, i, i));
1535
  }
1536
 
1537
  /**
1538
   * Sets the {@link #model} property of the list to a new anonymous
1539
   * {@link AbstractListModel} subclass which accesses the provided Object
1540
   * array directly.
1541
   *
1542
   * @param listData The object array to build a new list model on
1543
   * @see #setModel
1544
   */
1545
  public void setListData(final Object[] listData)
1546
  {
1547
    setModel(new AbstractListModel()
1548
        {
1549
          public int getSize()
1550
          {
1551
            return listData.length;
1552
          }
1553
 
1554
          public Object getElementAt(int i)
1555
          {
1556
            return listData[i];
1557
          }
1558
        });
1559
  }
1560
 
1561
  /**
1562
   * Sets the {@link #model} property of the list to a new anonymous {@link
1563
   * AbstractListModel} subclass which accesses the provided vector
1564
   * directly.
1565
   *
1566
   * @param listData The object array to build a new list model on
1567
   * @see #setModel
1568
   */
1569
  public void setListData(final Vector listData)
1570
  {
1571
    setModel(new AbstractListModel()
1572
        {
1573
          public int getSize()
1574
          {
1575
            return listData.size();
1576
          }
1577
 
1578
          public Object getElementAt(int i)
1579
          {
1580
            return listData.elementAt(i);
1581
          }
1582
        });
1583
  }
1584
 
1585
  /**
1586
   * Gets the value of the {@link #cellRenderer} property.
1587
   *
1588
   * @return The current value of the property
1589
   */
1590
  public ListCellRenderer getCellRenderer()
1591
  {
1592
    return cellRenderer;
1593
  }
1594
 
1595
  /**
1596
   * Sets the value of the {@link #getCellRenderer} property.
1597
   *
1598
   * @param renderer The new property value
1599
   */
1600
  public void setCellRenderer(ListCellRenderer renderer)
1601
  {
1602
    if (cellRenderer == renderer)
1603
      return;
1604
 
1605
    ListCellRenderer old = cellRenderer;
1606
    cellRenderer = renderer;
1607
    firePropertyChange("cellRenderer", old, renderer);
1608
    revalidate();
1609
    repaint();
1610
  }
1611
 
1612
  /**
1613
   * Gets the value of the {@link #model} property.
1614
   *
1615
   * @return The current value of the property
1616
   */
1617
  public ListModel getModel()
1618
  {
1619
    return model;
1620
  }
1621
 
1622
  /**
1623
   * Sets the value of the {@link #model} property. The list's {@link
1624
   * #listListener} is unsubscribed from the existing model, if it exists,
1625
   * and re-subscribed to the new model.
1626
   *
1627
   * @param model  the new model (<code>null</code> not permitted).
1628
   *
1629
   * @throws IllegalArgumentException if <code>model</code> is
1630
   *         <code>null</code>.
1631
   */
1632
  public void setModel(ListModel model)
1633
  {
1634
    if (model == null)
1635
      throw new IllegalArgumentException("Null 'model' argument.");
1636
    if (this.model == model)
1637
      return;
1638
 
1639
    if (this.model != null)
1640
      this.model.removeListDataListener(listListener);
1641
 
1642
    ListModel old = this.model;
1643
    this.model = model;
1644
 
1645
    if (this.model != null)
1646
      this.model.addListDataListener(listListener);
1647
 
1648
    firePropertyChange("model", old, model);
1649
    revalidate();
1650
    repaint();
1651
  }
1652
 
1653
 
1654
  public ListSelectionModel getSelectionModel()
1655
  {
1656
    return selectionModel;
1657
  }
1658
 
1659
  /**
1660
   * Sets the value of the {@link #selectionModel} property. The list's
1661
   * {@link #listListener} is unsubscribed from the existing selection
1662
   * model, if it exists, and re-subscribed to the new selection model.
1663
   *
1664
   * @param model The new property value
1665
   */
1666
  public void setSelectionModel(ListSelectionModel model)
1667
  {
1668
    if (selectionModel == model)
1669
      return;
1670
 
1671
    if (selectionModel != null)
1672
      selectionModel.removeListSelectionListener(listListener);
1673
 
1674
    ListSelectionModel old = selectionModel;
1675
    selectionModel = model;
1676
 
1677
    if (selectionModel != null)
1678
      selectionModel.addListSelectionListener(listListener);
1679
 
1680
    firePropertyChange("selectionModel", old, model);
1681
    revalidate();
1682
    repaint();
1683
  }
1684
 
1685
  /**
1686
   * Gets the value of the UI property.
1687
   *
1688
   * @return The current property value
1689
   */
1690
  public ListUI getUI()
1691
  {
1692
    return (ListUI) ui;
1693
  }
1694
 
1695
  /**
1696
   * Sets the value of the UI property.
1697
   *
1698
   * @param ui The new property value
1699
   */
1700
  public void setUI(ListUI ui)
1701
  {
1702
    super.setUI(ui);
1703
  }
1704
 
1705
  /**
1706
   * Calls {@link #setUI} with the {@link ListUI} subclass
1707
   * returned from calling {@link UIManager#getUI}.
1708
   */
1709
  public void updateUI()
1710
  {
1711
    setUI((ListUI) UIManager.getUI(this));
1712
  }
1713
 
1714
  /**
1715
   * Return the class identifier for the list's UI property.  This should
1716
   * be the constant string <code>"ListUI"</code>, and map to an
1717
   * appropriate UI class in the {@link UIManager}.
1718
   *
1719
   * @return The class identifier
1720
   */
1721
  public String getUIClassID()
1722
  {
1723
    return "ListUI";
1724
  }
1725
 
1726
 
1727
  /**
1728
   * Returns the current value of the {@link #prototypeCellValue}
1729
   * property. This property holds a reference to a "prototype" data value
1730
   * -- typically a String -- which is used to calculate the {@link
1731
   * #fixedCellWidth} and {@link #fixedCellHeight} properties, using the
1732
   * {@link #cellRenderer} property to acquire a component to render the
1733
   * prototype.
1734
   *
1735
   * @return The current prototype cell value
1736
   * @see #setPrototypeCellValue
1737
   */
1738
  public Object getPrototypeCellValue()
1739
  {
1740
    return prototypeCellValue;
1741
  }
1742
 
1743
  /**
1744
   * <p>Set the {@link #prototypeCellValue} property. This property holds a
1745
   * reference to a "prototype" data value -- typically a String -- which
1746
   * is used to calculate the {@link #fixedCellWidth} and {@link
1747
   * #fixedCellHeight} properties, using the {@link #cellRenderer} property
1748
   * to acquire a component to render the prototype.</p>
1749
   *
1750
   * <p>It is important that you <em>not</em> set this value to a
1751
   * component. It has to be a <em>data value</em> such as the objects you
1752
   * would find in the list's model. Setting it to a component will have
1753
   * undefined (and undesirable) affects. </p>
1754
   *
1755
   * @param obj The new prototype cell value
1756
   * @see #getPrototypeCellValue
1757
   */
1758
  public void setPrototypeCellValue(Object obj)
1759
  {
1760
    if (prototypeCellValue == obj)
1761
      return;
1762
 
1763
    Object old = prototypeCellValue;
1764
    Component comp = getCellRenderer()
1765
      .getListCellRendererComponent(this, obj, 0, false, false);
1766
    Dimension d = comp.getPreferredSize();
1767
    fixedCellWidth = d.width;
1768
    fixedCellHeight = d.height;
1769
    prototypeCellValue = obj;
1770
    firePropertyChange("prototypeCellValue", old, obj);
1771
  }
1772
 
1773
  public AccessibleContext getAccessibleContext()
1774
  {
1775
    return new AccessibleJList();
1776
  }
1777
 
1778
  /**
1779
   * Returns a size indicating how much space this list would like to
1780
   * consume, when contained in a scrollable viewport. This is part of the
1781
   * {@link Scrollable} interface, which interacts with {@link
1782
   * ScrollPaneLayout} and {@link JViewport} to define scrollable objects.
1783
   *
1784
   * @return The preferred size
1785
   */
1786
  public Dimension getPreferredScrollableViewportSize()
1787
  {
1788
    //If the layout orientation is not VERTICAL, then this will 
1789
    //return the value from getPreferredSize. The current ListUI is 
1790
    //expected to override getPreferredSize to return an appropriate value.
1791
    if (getLayoutOrientation() != VERTICAL)
1792
      return getPreferredSize();
1793
 
1794
    int size = getModel().getSize();
1795
 
1796
    // Trivial case: if fixedCellWidth and fixedCellHeight were set 
1797
    // just use them
1798
    if (fixedCellHeight != -1 && fixedCellWidth != -1)
1799
      return new Dimension(fixedCellWidth, size * fixedCellHeight);
1800
 
1801
    // If the model is empty we use 16 * the number of visible rows
1802
    // for the height and either fixedCellWidth (if set) or 256
1803
    // for the width
1804
    if (size == 0)
1805
      {
1806
        if (fixedCellWidth == -1)
1807
          return new Dimension(256, 16 * getVisibleRowCount());
1808
        else
1809
          return new Dimension(fixedCellWidth, 16 * getVisibleRowCount());
1810
      }
1811
 
1812
    // Calculate the width: if fixedCellWidth was set use that, otherwise
1813
    // use the preferredWidth
1814
    int prefWidth;
1815
    if (fixedCellWidth != -1)
1816
      prefWidth = fixedCellWidth;
1817
    else
1818
      prefWidth = getPreferredSize().width;
1819
 
1820
    // Calculate the height: if fixedCellHeight was set use that, otherwise
1821
    // use the height of the first row multiplied by the number of visible
1822
    // rows
1823
    int prefHeight;
1824
    if (fixedCellHeight != -1)
1825
      prefHeight = fixedCellHeight;
1826
    else
1827
      prefHeight = getVisibleRowCount() * getCellBounds(0, 0).height;
1828
 
1829
    return new Dimension (prefWidth, prefHeight);
1830
  }
1831
 
1832
  /**
1833
   * <p>Return the number of pixels the list must scroll in order to move a
1834
   * "unit" of the list into the provided visible rectangle. When the
1835
   * provided direction is positive, the call describes a "downwards"
1836
   * scroll, which will be exposing a cell at a <em>greater</em> index in
1837
   * the list than those elements currently showing. Then the provided
1838
   * direction is negative, the call describes an "upwards" scroll, which
1839
   * will be exposing a cell at a <em>lesser</em> index in the list than
1840
   * those elements currently showing.</p>
1841
   *
1842
   * <p>If the provided orientation is <code>HORIZONTAL</code>, the above
1843
   * comments refer to "rightwards" for positive direction, and "leftwards"
1844
   * for negative.</p>
1845
   *
1846
   *
1847
   * @param visibleRect The rectangle to scroll an element into
1848
   * @param orientation One of the numeric consants <code>VERTICAL</code>
1849
   * or <code>HORIZONTAL</code>
1850
   * @param direction An integer indicating the scroll direction: positive means
1851
   * forwards (down, right), negative means backwards (up, left)
1852
   *
1853
   * @return The scrollable unit increment, in pixels
1854
   */
1855
  public int getScrollableUnitIncrement(Rectangle visibleRect,
1856
                                        int orientation, int direction)
1857
  {
1858
    ListUI lui = this.getUI();
1859
    if (orientation == SwingConstants.VERTICAL)
1860
      {
1861
        if (direction > 0)
1862
          {
1863
            // Scrolling down
1864
            Point bottomLeft = new Point(visibleRect.x,
1865
                                         visibleRect.y + visibleRect.height);
1866
            int curIdx = lui.locationToIndex(this, bottomLeft);
1867
            Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx);
1868
            if (curBounds.y + curBounds.height == bottomLeft.y)
1869
              {
1870
                // we are at the exact bottom of the current cell, so we 
1871
                // are being asked to scroll to the end of the next one
1872
                if (curIdx + 1 < model.getSize())
1873
                  {
1874
                    // there *is* a next item in the list
1875
                    Rectangle nxtBounds = lui.getCellBounds(this, curIdx + 1, curIdx + 1);
1876
                    return nxtBounds.height;
1877
                  }
1878
                else
1879
                  {
1880
                    // no next item, no advance possible
1881
                    return 0;
1882
                  }
1883
              }
1884
            else
1885
              {
1886
                // we are part way through an existing cell, so we are being
1887
                // asked to scroll to the bottom of it
1888
                return (curBounds.y + curBounds.height) - bottomLeft.y;
1889
              }
1890
          }
1891
        else
1892
          {
1893
            // scrolling up
1894
            Point topLeft = new Point(visibleRect.x, visibleRect.y);
1895
            int curIdx = lui.locationToIndex(this, topLeft);
1896
            Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx);
1897
            if (curBounds.y == topLeft.y)
1898
              {
1899
                // we are at the exact top of the current cell, so we 
1900
                // are being asked to scroll to the top of the previous one
1901
                if (curIdx > 0)
1902
                  {
1903
                    // there *is* a previous item in the list
1904
                    Rectangle nxtBounds = lui.getCellBounds(this, curIdx - 1, curIdx - 1);
1905
                    return -nxtBounds.height;
1906
                  }
1907
                else
1908
                  {
1909
                    // no previous item, no advance possible
1910
                    return 0;
1911
                  }
1912
              }
1913
            else
1914
              {
1915
                // we are part way through an existing cell, so we are being
1916
                // asked to scroll to the top of it
1917
                return curBounds.y - topLeft.y;
1918
              }
1919
          }
1920
      }
1921
 
1922
    // FIXME: handle horizontal scrolling (also wrapping?)
1923
    return 1;
1924
  }
1925
 
1926
  /**
1927
   * <p>Return the number of pixels the list must scroll in order to move a
1928
   * "block" of the list into the provided visible rectangle. When the
1929
   * provided direction is positive, the call describes a "downwards"
1930
   * scroll, which will be exposing a cell at a <em>greater</em> index in
1931
   * the list than those elements currently showing. Then the provided
1932
   * direction is negative, the call describes an "upwards" scroll, which
1933
   * will be exposing a cell at a <em>lesser</em> index in the list than
1934
   * those elements currently showing.</p>
1935
   *
1936
   * <p>If the provided orientation is <code>HORIZONTAL</code>, the above
1937
   * comments refer to "rightwards" for positive direction, and "leftwards"
1938
   * for negative.</p>
1939
   *
1940
   *
1941
   * @param visibleRect The rectangle to scroll an element into
1942
   * @param orientation One of the numeric consants <code>VERTICAL</code>
1943
   * or <code>HORIZONTAL</code>
1944
   * @param direction An integer indicating the scroll direction: positive means
1945
   * forwards (down, right), negative means backwards (up, left)
1946
   *
1947
   * @return The scrollable unit increment, in pixels
1948
   */
1949
  public int getScrollableBlockIncrement(Rectangle visibleRect,
1950
                                         int orientation, int direction)
1951
  {
1952
      if (orientation == VERTICAL)
1953
          return visibleRect.height * direction;
1954
      else
1955
          return visibleRect.width * direction;
1956
  }
1957
 
1958
  /**
1959
   * Gets the value of the <code>scrollableTracksViewportWidth</code> property.
1960
   *
1961
   * @return <code>true</code> if the viewport is larger (horizontally)
1962
   * than the list and the list should be expanded to fit the viewport;
1963
   * <code>false</code> if the viewport is smaller than the list and the
1964
   * list should scroll (horizontally) within the viewport
1965
   */
1966
  public boolean getScrollableTracksViewportWidth()
1967
  {
1968
    Component parent = getParent();
1969
    boolean retVal = false;
1970
    if (parent instanceof JViewport)
1971
      {
1972
        JViewport viewport = (JViewport) parent;
1973
        Dimension pref = getPreferredSize();
1974
        if (viewport.getSize().width > pref.width)
1975
          retVal = true;
1976
        if ((getLayoutOrientation() == HORIZONTAL_WRAP)
1977
            && (getVisibleRowCount() <= 0))
1978
          retVal = true;
1979
      }
1980
    return retVal;
1981
  }
1982
 
1983
  /**
1984
   * Gets the value of the </code>scrollableTracksViewportWidth</code> property.
1985
   *
1986
   * @return <code>true</code> if the viewport is larger (vertically)
1987
   * than the list and the list should be expanded to fit the viewport;
1988
   * <code>false</code> if the viewport is smaller than the list and the
1989
   * list should scroll (vertically) within the viewport
1990
   */
1991
  public boolean getScrollableTracksViewportHeight()
1992
  {
1993
    Component parent = getParent();
1994
    boolean retVal = false;
1995
    if (parent instanceof JViewport)
1996
      {
1997
        JViewport viewport = (JViewport) parent;
1998
        Dimension pref = getPreferredSize();
1999
        if (viewport.getSize().height > pref.height)
2000
          retVal = true;
2001
        if ((getLayoutOrientation() == VERTICAL_WRAP)
2002
            && (getVisibleRowCount() <= 0))
2003
          retVal = true;
2004
      }
2005
    return retVal;
2006
  }
2007
 
2008
  public int getAnchorSelectionIndex()
2009
  {
2010
    return selectionModel.getAnchorSelectionIndex();
2011
  }
2012
 
2013
  public int getLeadSelectionIndex()
2014
  {
2015
    return selectionModel.getLeadSelectionIndex();
2016
  }
2017
 
2018
  public int getMinSelectionIndex()
2019
  {
2020
    return selectionModel.getMaxSelectionIndex();
2021
  }
2022
 
2023
  public int getMaxSelectionIndex()
2024
  {
2025
    return selectionModel.getMaxSelectionIndex();
2026
  }
2027
 
2028
  public void clearSelection()
2029
  {
2030
    selectionModel.clearSelection();
2031
  }
2032
 
2033
  public void setSelectionInterval(int anchor, int lead)
2034
  {
2035
    selectionModel.setSelectionInterval(anchor, lead);
2036
  }
2037
 
2038
  public void addSelectionInterval(int anchor, int lead)
2039
  {
2040
    selectionModel.addSelectionInterval(anchor, lead);
2041
  }
2042
 
2043
  public void removeSelectionInterval(int index0, int index1)
2044
  {
2045
    selectionModel.removeSelectionInterval(index0, index1);
2046
  }
2047
 
2048
  /**
2049
   * Returns the value of the <code>valueIsAdjusting</code> property.
2050
   *
2051
   * @return the value
2052
   */
2053
  public boolean getValueIsAdjusting()
2054
  {
2055
    return valueIsAdjusting;
2056
  }
2057
 
2058
  /**
2059
   * Sets the <code>valueIsAdjusting</code> property.
2060
   *
2061
   * @param isAdjusting the new value
2062
   */
2063
  public void setValueIsAdjusting(boolean isAdjusting)
2064
  {
2065
    valueIsAdjusting = isAdjusting;
2066
  }
2067
 
2068
  /**
2069
   * Return the value of the <code>dragEnabled</code> property.
2070
   *
2071
   * @return the value
2072
   *
2073
   * @since 1.4
2074
   */
2075
  public boolean getDragEnabled()
2076
  {
2077
    return dragEnabled;
2078
  }
2079
 
2080
  /**
2081
   * Set the <code>dragEnabled</code> property.
2082
   *
2083
   * @param enabled new value
2084
   *
2085
   * @since 1.4
2086
   */
2087
  public void setDragEnabled(boolean enabled)
2088
  {
2089
    dragEnabled = enabled;
2090
  }
2091
 
2092
  /**
2093
   * Returns the layout orientation.
2094
   *
2095
   * @return the orientation, one of <code>JList.VERTICAL</code>,
2096
   * <code>JList.VERTICAL_WRAP</code> and <code>JList.HORIZONTAL_WRAP</code>
2097
   *
2098
   * @since 1.4
2099
   */
2100
  public int getLayoutOrientation()
2101
  {
2102
    return layoutOrientation;
2103
  }
2104
 
2105
  /**
2106
   * Sets the layout orientation.
2107
   *
2108
   * @param orientation the orientation to set, one of <code>JList.VERTICAL</code>,
2109
   * <code>JList.VERTICAL_WRAP</code> and <code>JList.HORIZONTAL_WRAP</code>
2110
   *
2111
   * @since 1.4
2112
   */
2113
  public void setLayoutOrientation(int orientation)
2114
  {
2115
    if (layoutOrientation == orientation)
2116
      return;
2117
 
2118
    int old = layoutOrientation;
2119
    layoutOrientation = orientation;
2120
    firePropertyChange("layoutOrientation", old, orientation);
2121
  }
2122
 
2123
  /**
2124
   * Returns the bounds of the rectangle that encloses both list cells
2125
   * with index0 and index1.
2126
   *
2127
   * @param index0 the index of the first cell
2128
   * @param index1 the index of the second cell
2129
   *
2130
   * @return  the bounds of the rectangle that encloses both list cells
2131
   *     with index0 and index1, <code>null</code> if one of the indices is
2132
   *     not valid
2133
   */
2134
  public Rectangle getCellBounds(int index0, int index1)
2135
  {
2136
    return getUI().getCellBounds(this, index0, index1);
2137
  }
2138
 
2139
  /**
2140
   * Returns the next list element (beginning from <code>startIndex</code>
2141
   * that starts with <code>prefix</code>. Searching is done in the direction
2142
   * specified by <code>bias</code>.
2143
   *
2144
   * @param prefix the prefix to search for in the cell values
2145
   * @param startIndex the index where to start searching from
2146
   * @param bias the search direction, either {@link Position.Bias#Forward}
2147
   *     or {@link Position.Bias#Backward}
2148
   *
2149
   * @return the index of the found element or -1 if no such element has
2150
   *     been found
2151
   *
2152
   * @throws IllegalArgumentException if prefix is <code>null</code> or
2153
   *     startIndex is not valid
2154
   *
2155
   * @since 1.4
2156
   */
2157
  public int getNextMatch(String prefix, int startIndex, Position.Bias bias)
2158
  {
2159
    if (prefix == null)
2160
      throw new IllegalArgumentException("The argument 'prefix' must not be"
2161
                                         + " null.");
2162
    if (startIndex < 0)
2163
      throw new IllegalArgumentException("The argument 'startIndex' must not"
2164
                                         + " be less than zero.");
2165
 
2166
    int size = model.getSize();
2167
    if (startIndex > model.getSize())
2168
      throw new IllegalArgumentException("The argument 'startIndex' must not"
2169
                                         + " be greater than the number of"
2170
                                         + " elements in the ListModel.");
2171
 
2172
    int index = -1;
2173
    if (bias == Position.Bias.Forward)
2174
      {
2175
        for (int i = startIndex; i < size; i++)
2176
          {
2177
            String item = model.getElementAt(i).toString();
2178
            if (item.startsWith(prefix))
2179
              {
2180
                index = i;
2181
                break;
2182
              }
2183
          }
2184
      }
2185
    else
2186
      {
2187
        for (int i = startIndex; i >= 0; i--)
2188
          {
2189
            String item = model.getElementAt(i).toString();
2190
            if (item.startsWith(prefix))
2191
              {
2192
                index = i;
2193
                break;
2194
              }
2195
          }
2196
      }
2197
    return index;
2198
  }
2199
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.