Source for javax.swing.JList

   1: /* JList.java --
   2:    Copyright (C) 2002, 2003, 2004, 2005, 2006,  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:    * This property indicates a <em>preference</em> for the number of rows
 949:    * displayed in the list, and will scale the
 950:    * {@link #getPreferredScrollableViewportSize} property accordingly. The actual
 951:    * number of displayed rows, when the list is placed in a real {@link
 952:    * JViewport} or other component, may be greater or less than this number.
 953:    */
 954:   int visibleRowCount;
 955: 
 956:   /**
 957:    * Fire a {@link ListSelectionEvent} to all the registered 
 958:    * ListSelectionListeners.
 959:    * 
 960:    * @param firstIndex  the lowest index covering the selection change.
 961:    * @param lastIndex  the highest index covering the selection change.
 962:    * @param isAdjusting  a flag indicating if this event is one in a series
 963:    *     of events updating the selection.
 964:    */
 965:   protected void fireSelectionValueChanged(int firstIndex, int lastIndex, 
 966:                                            boolean isAdjusting) 
 967:</