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