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