1. /*
  2. * @(#)JTable.java 1.208 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.util.*;
  9. import java.applet.Applet;
  10. import java.awt.*;
  11. import java.awt.event.*;
  12. import java.beans.*;
  13. import java.io.Serializable;
  14. import java.io.ObjectOutputStream;
  15. import java.io.ObjectInputStream;
  16. import java.io.IOException;
  17. import javax.accessibility.*;
  18. import javax.swing.event.*;
  19. import javax.swing.plaf.*;
  20. import javax.swing.table.*;
  21. import javax.swing.border.*;
  22. import java.text.NumberFormat;
  23. import java.text.DateFormat;
  24. /**
  25. * The <code>JTable</code> is used to display and edit regular two-dimensional tables
  26. * of cells.
  27. * See <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/table.html">How to Use Tables</a>
  28. * in <em>The Java Tutorial</em>
  29. * for task-oriented documentation and examples of using <code>JTable</code>.
  30. *
  31. * <p>
  32. * The <code>JTable</code> has many
  33. * facilities that make it possible to customize its rendering and editing
  34. * but provides defaults for these features so that simple tables can be
  35. * set up easily. For example, to set up a table with 10 rows and 10
  36. * columns of numbers:
  37. * <p>
  38. * <pre>
  39. * TableModel dataModel = new AbstractTableModel() {
  40. * public int getColumnCount() { return 10; }
  41. * public int getRowCount() { return 10;}
  42. * public Object getValueAt(int row, int col) { return new Integer(row*col); }
  43. * };
  44. * JTable table = new JTable(dataModel);
  45. * JScrollPane scrollpane = new JScrollPane(table);
  46. * </pre>
  47. * <p>
  48. * Note that if you wish to use a <code>JTable</code> in a standalone
  49. * view (outside of a <code>JScrollPane</code>) and want the header
  50. * displayed, you can get it using {@link #getTableHeader} and
  51. * display it separately.
  52. * <p>
  53. * When designing applications that use the <code>JTable</code> it is worth paying
  54. * close attention to the data structures that will represent the table's data.
  55. * The <code>DefaultTableModel</code> is a model implementation that
  56. * uses a <code>Vector</code> of <code>Vector</code>s of <code>Object</code>s to
  57. * store the cell values. As well as copying the data from an
  58. * application into the <code>DefaultTableModel</code>,
  59. * it is also possible to wrap the data in the methods of the
  60. * <code>TableModel</code> interface so that the data can be passed to the
  61. * <code>JTable</code> directly, as in the example above. This often results
  62. * in more efficient applications because the model is free to choose the
  63. * internal representation that best suits the data.
  64. * A good rule of thumb for deciding whether to use the <code>AbstractTableModel</code>
  65. * or the <code>DefaultTableModel</code> is to use the <code>AbstractTableModel</code>
  66. * as the base class for creating subclasses and the <code>DefaultTableModel</code>
  67. * when subclassing is not required.
  68. * <p>
  69. * The "TableExample" directory in the demo area of the source distribution
  70. * gives a number of complete examples of <code>JTable</code> usage,
  71. * covering how the <code>JTable</code> can be used to provide an
  72. * editable view of data taken from a database and how to modify
  73. * the columns in the display to use specialized renderers and editors.
  74. * <p>
  75. * The <code>JTable</code> uses integers exclusively to refer to both the rows and the columns
  76. * of the model that it displays. The <code>JTable</code> simply takes a tabular range of cells
  77. * and uses <code>getValueAt(int, int)</code> to retrieve the
  78. * values from the model during painting.
  79. * <p>
  80. * By default, columns may be rearranged in the <code>JTable</code> so that the
  81. * view's columns appear in a different order to the columns in the model.
  82. * This does not affect the implementation of the model at all: when the
  83. * columns are reordered, the <code>JTable</code> maintains the new order of the columns
  84. * internally and converts its column indices before querying the model.
  85. * <p>
  86. * So, when writing a <code>TableModel</code>, it is not necessary to listen for column
  87. * reordering events as the model will be queried in its own coordinate
  88. * system regardless of what is happening in the view.
  89. * In the examples area there is a demonstration of a sorting algorithm making
  90. * use of exactly this technique to interpose yet another coordinate system
  91. * where the order of the rows is changed, rather than the order of the columns.
  92. * <p>
  93. * As for all <code>JComponent</code> classes, you can use
  94. * {@link InputMap} and {@link ActionMap} to associate an
  95. * {@link Action} object with a {@link KeyStroke} and execute the
  96. * action under specified conditions.
  97. * <p>
  98. * For the keyboard keys used by this component in the standard Look and
  99. * Feel (L&F) renditions, see the
  100. * <a href="doc-files/Key-Index.html#JTable"><code>JTable</code> key assignments</a>.
  101. * <p>
  102. * <strong>Warning:</strong>
  103. * Serialized objects of this class will not be compatible with
  104. * future Swing releases. The current serialization support is
  105. * appropriate for short term storage or RMI between applications running
  106. * the same version of Swing. As of 1.4, support for long term storage
  107. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  108. * has been added to the <code>java.beans</code> package.
  109. * Please see {@link java.beans.XMLEncoder}.
  110. *
  111. *
  112. * @beaninfo
  113. * attribute: isContainer false
  114. * description: A component which displays data in a two dimensional grid.
  115. *
  116. * @version 1.208 01/23/03
  117. * @author Philip Milne
  118. */
  119. /* The first versions of the JTable, contained in Swing-0.1 through
  120. * Swing-0.4, were written by Alan Chung.
  121. */
  122. public class JTable extends JComponent implements TableModelListener, Scrollable,
  123. TableColumnModelListener, ListSelectionListener, CellEditorListener,
  124. Accessible
  125. {
  126. //
  127. // Static Constants
  128. //
  129. /**
  130. * @see #getUIClassID
  131. * @see #readObject
  132. */
  133. private static final String uiClassID = "TableUI";
  134. /** Do not adjust column widths automatically; use a scrollbar. */
  135. public static final int AUTO_RESIZE_OFF = 0;
  136. /** When a column is adjusted in the UI, adjust the next column the opposite way. */
  137. public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
  138. /** During UI adjustment, change subsequent columns to preserve the total width;
  139. * this is the default behavior. */
  140. public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
  141. /** During all resize operations, apply adjustments to the last column only. */
  142. public static final int AUTO_RESIZE_LAST_COLUMN = 3;
  143. /** During all resize operations, proportionately resize all columns. */
  144. public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
  145. //
  146. // Instance Variables
  147. //
  148. /** The <code>TableModel</code> of the table. */
  149. protected TableModel dataModel;
  150. /** The <code>TableColumnModel</code> of the table. */
  151. protected TableColumnModel columnModel;
  152. /** The <code>ListSelectionModel</code> of the table, used to keep track of row selections. */
  153. protected ListSelectionModel selectionModel;
  154. /** The <code>TableHeader</code> working with the table. */
  155. protected JTableHeader tableHeader;
  156. /** The height in pixels of each row in the table. */
  157. protected int rowHeight;
  158. /** The height in pixels of the margin between the cells in each row. */
  159. protected int rowMargin;
  160. /** The color of the grid. */
  161. protected Color gridColor;
  162. /** The table draws horizontal lines between cells if <code>showHorizontalLines</code> is true. */
  163. protected boolean showHorizontalLines;
  164. /** The table draws vertical lines between cells if <code>showVerticalLines</code> is true. */
  165. protected boolean showVerticalLines;
  166. /**
  167. * Determines if the table automatically resizes the
  168. * width of the table's columns to take up the entire width of the
  169. * table, and how it does the resizing.
  170. */
  171. protected int autoResizeMode;
  172. /**
  173. * The table will query the <code>TableModel</code> to build the default
  174. * set of columns if this is true.
  175. */
  176. protected boolean autoCreateColumnsFromModel;
  177. /** Used by the <code>Scrollable</code> interface to determine the initial visible area. */
  178. protected Dimension preferredViewportSize;
  179. /** True if row selection is allowed in this table. */
  180. protected boolean rowSelectionAllowed;
  181. /**
  182. * Obsolete as of Java 2 platform v1.3. Please use the
  183. * <code>rowSelectionAllowed</code> property and the
  184. * <code>columnSelectionAllowed</code> property of the
  185. * <code>columnModel</code> instead. Or use the
  186. * method <code>getCellSelectionEnabled</code>.
  187. */
  188. /*
  189. * If true, both a row selection and a column selection
  190. * can be non-empty at the same time, the selected cells are the
  191. * the cells whose row and column are both selected.
  192. */
  193. protected boolean cellSelectionEnabled;
  194. /** If editing, the <code>Component</code> that is handling the editing. */
  195. transient protected Component editorComp;
  196. /**
  197. * The object that overwrites the screen real estate occupied by the
  198. * current cell and allows the user to change its contents.
  199. */
  200. transient protected TableCellEditor cellEditor;
  201. /** Identifies the column of the cell being edited. */
  202. transient protected int editingColumn;
  203. /** Identifies the row of the cell being edited. */
  204. transient protected int editingRow;
  205. /**
  206. * A table of objects that display the contents of a cell,
  207. * indexed by class as declared in <code>getColumnClass</code>
  208. * in the <code>TableModel</code> interface.
  209. */
  210. transient protected Hashtable defaultRenderersByColumnClass;
  211. /**
  212. * A table of objects that display and edit the contents of a cell,
  213. * indexed by class as declared in <code>getColumnClass</code>
  214. * in the <code>TableModel</code> interface.
  215. */
  216. transient protected Hashtable defaultEditorsByColumnClass;
  217. /** The foreground color of selected cells. */
  218. protected Color selectionForeground;
  219. /** The background color of selected cells. */
  220. protected Color selectionBackground;
  221. //
  222. // Private state
  223. //
  224. private SizeSequence rowModel;
  225. private boolean dragEnabled;
  226. private boolean surrendersFocusOnKeystroke;
  227. private PropertyChangeListener editorRemover = null;
  228. /**
  229. * The last value of getValueIsAdjusting from the column selection models
  230. * columnSelectionChanged notification. Used to test if a repaint is
  231. * needed.
  232. */
  233. private boolean columnSelectionAdjusting;
  234. /**
  235. * The last value of getValueIsAdjusting from the row selection models
  236. * valueChanged notification. Used to test if a repaint is needed.
  237. */
  238. private boolean rowSelectionAdjusting;
  239. //
  240. // Constructors
  241. //
  242. /**
  243. * Constructs a default <code>JTable</code> that is initialized with a default
  244. * data model, a default column model, and a default selection
  245. * model.
  246. *
  247. * @see #createDefaultDataModel
  248. * @see #createDefaultColumnModel
  249. * @see #createDefaultSelectionModel
  250. */
  251. public JTable() {
  252. this(null, null, null);
  253. }
  254. /**
  255. * Constructs a <code>JTable</code> that is initialized with
  256. * <code>dm</code> as the data model, a default column model,
  257. * and a default selection model.
  258. *
  259. * @param dm the data model for the table
  260. * @see #createDefaultColumnModel
  261. * @see #createDefaultSelectionModel
  262. */
  263. public JTable(TableModel dm) {
  264. this(dm, null, null);
  265. }
  266. /**
  267. * Constructs a <code>JTable</code> that is initialized with
  268. * <code>dm</code> as the data model, <code>cm</code>
  269. * as the column model, and a default selection model.
  270. *
  271. * @param dm the data model for the table
  272. * @param cm the column model for the table
  273. * @see #createDefaultSelectionModel
  274. */
  275. public JTable(TableModel dm, TableColumnModel cm) {
  276. this(dm, cm, null);
  277. }
  278. /**
  279. * Constructs a <code>JTable</code> that is initialized with
  280. * <code>dm</code> as the data model, <code>cm</code> as the
  281. * column model, and <code>sm</code> as the selection model.
  282. * If any of the parameters are <code>null</code> this method
  283. * will initialize the table with the corresponding default model.
  284. * The <code>autoCreateColumnsFromModel</code> flag is set to false
  285. * if <code>cm</code> is non-null, otherwise it is set to true
  286. * and the column model is populated with suitable
  287. * <code>TableColumns</code> for the columns in <code>dm</code>.
  288. *
  289. * @param dm the data model for the table
  290. * @param cm the column model for the table
  291. * @param sm the row selection model for the table
  292. * @see #createDefaultDataModel
  293. * @see #createDefaultColumnModel
  294. * @see #createDefaultSelectionModel
  295. */
  296. public JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
  297. super();
  298. setLayout(null);
  299. setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
  300. JComponent.getManagingFocusForwardTraversalKeys());
  301. setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
  302. JComponent.getManagingFocusBackwardTraversalKeys());
  303. if (cm == null) {
  304. cm = createDefaultColumnModel();
  305. autoCreateColumnsFromModel = true;
  306. }
  307. setColumnModel(cm);
  308. if (sm == null) {
  309. sm = createDefaultSelectionModel();
  310. }
  311. setSelectionModel(sm);
  312. // Set the model last, that way if the autoCreatColumnsFromModel has
  313. // been set above, we will automatically populate an empty columnModel
  314. // with suitable columns for the new model.
  315. if (dm == null) {
  316. dm = createDefaultDataModel();
  317. }
  318. setModel(dm);
  319. initializeLocalVars();
  320. updateUI();
  321. }
  322. /**
  323. * Constructs a <code>JTable</code> with <code>numRows</code>
  324. * and <code>numColumns</code> of empty cells using
  325. * <code>DefaultTableModel</code>. The columns will have
  326. * names of the form "A", "B", "C", etc.
  327. *
  328. * @param numRows the number of rows the table holds
  329. * @param numColumns the number of columns the table holds
  330. * @see javax.swing.table.DefaultTableModel
  331. */
  332. public JTable(int numRows, int numColumns) {
  333. this(new DefaultTableModel(numRows, numColumns));
  334. }
  335. /**
  336. * Constructs a <code>JTable</code> to display the values in the
  337. * <code>Vector</code> of <code>Vectors</code>, <code>rowData</code>,
  338. * with column names, <code>columnNames</code>. The
  339. * <code>Vectors</code> contained in <code>rowData</code>
  340. * should contain the values for that row. In other words,
  341. * the value of the cell at row 1, column 5 can be obtained
  342. * with the following code:
  343. * <p>
  344. * <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre>
  345. * <p>
  346. * @param rowData the data for the new table
  347. * @param columnNames names of each column
  348. */
  349. public JTable(Vector rowData, Vector columnNames) {
  350. this(new DefaultTableModel(rowData, columnNames));
  351. }
  352. /**
  353. * Constructs a <code>JTable</code> to display the values in the two dimensional array,
  354. * <code>rowData</code>, with column names, <code>columnNames</code>.
  355. * <code>rowData</code> is an array of rows, so the value of the cell at row 1,
  356. * column 5 can be obtained with the following code:
  357. * <p>
  358. * <pre> rowData[1][5]; </pre>
  359. * <p>
  360. * All rows must be of the same length as <code>columnNames</code>.
  361. * <p>
  362. * @param rowData the data for the new table
  363. * @param columnNames names of each column
  364. */
  365. public JTable(final Object[][] rowData, final Object[] columnNames) {
  366. this(new AbstractTableModel() {
  367. public String getColumnName(int column) { return columnNames[column].toString(); }
  368. public int getRowCount() { return rowData.length; }
  369. public int getColumnCount() { return columnNames.length; }
  370. public Object getValueAt(int row, int col) { return rowData[row][col]; }
  371. public boolean isCellEditable(int row, int column) { return true; }
  372. public void setValueAt(Object value, int row, int col) {
  373. rowData[row][col] = value;
  374. fireTableCellUpdated(row, col);
  375. }
  376. });
  377. }
  378. /**
  379. * Calls the <code>configureEnclosingScrollPane</code> method.
  380. *
  381. * @see #configureEnclosingScrollPane
  382. */
  383. public void addNotify() {
  384. super.addNotify();
  385. configureEnclosingScrollPane();
  386. }
  387. /**
  388. * If this <code>JTable</code> is the <code>viewportView</code> of an enclosing <code>JScrollPane</code>
  389. * (the usual situation), configure this <code>ScrollPane</code> by, amongst other things,
  390. * installing the table's <code>tableHeader</code> as the <code>columnHeaderView</code> of the scroll pane.
  391. * When a <code>JTable</code> is added to a <code>JScrollPane</code> in the usual way,
  392. * using <code>new JScrollPane(myTable)</code>, <code>addNotify</code> is
  393. * called in the <code>JTable</code> (when the table is added to the viewport).
  394. * <code>JTable</code>'s <code>addNotify</code> method in turn calls this method,
  395. * which is protected so that this default installation procedure can
  396. * be overridden by a subclass.
  397. *
  398. * @see #addNotify
  399. */
  400. protected void configureEnclosingScrollPane() {
  401. Container p = getParent();
  402. if (p instanceof JViewport) {
  403. Container gp = p.getParent();
  404. if (gp instanceof JScrollPane) {
  405. JScrollPane scrollPane = (JScrollPane)gp;
  406. // Make certain we are the viewPort's view and not, for
  407. // example, the rowHeaderView of the scrollPane -
  408. // an implementor of fixed columns might do this.
  409. JViewport viewport = scrollPane.getViewport();
  410. if (viewport == null || viewport.getView() != this) {
  411. return;
  412. }
  413. scrollPane.setColumnHeaderView(getTableHeader());
  414. // scrollPane.getViewport().setBackingStoreEnabled(true);
  415. Border border = scrollPane.getBorder();
  416. if (border == null || border instanceof UIResource) {
  417. scrollPane.setBorder(UIManager.getBorder("Table.scrollPaneBorder"));
  418. }
  419. }
  420. }
  421. }
  422. /**
  423. * Calls the <code>unconfigureEnclosingScrollPane</code> method.
  424. *
  425. * @see #unconfigureEnclosingScrollPane
  426. */
  427. public void removeNotify() {
  428. KeyboardFocusManager.getCurrentKeyboardFocusManager().
  429. removePropertyChangeListener("permanentFocusOwner", editorRemover);
  430. editorRemover = null;
  431. unconfigureEnclosingScrollPane();
  432. super.removeNotify();
  433. }
  434. /**
  435. * Reverses the effect of <code>configureEnclosingScrollPane</code>
  436. * by replacing the <code>columnHeaderView</code> of the enclosing
  437. * scroll pane with <code>null</code>. <code>JTable</code>'s
  438. * <code>removeNotify</code> method calls
  439. * this method, which is protected so that this default uninstallation
  440. * procedure can be overridden by a subclass.
  441. *
  442. * @see #removeNotify
  443. * @see #configureEnclosingScrollPane
  444. */
  445. protected void unconfigureEnclosingScrollPane() {
  446. Container p = getParent();
  447. if (p instanceof JViewport) {
  448. Container gp = p.getParent();
  449. if (gp instanceof JScrollPane) {
  450. JScrollPane scrollPane = (JScrollPane)gp;
  451. // Make certain we are the viewPort's view and not, for
  452. // example, the rowHeaderView of the scrollPane -
  453. // an implementor of fixed columns might do this.
  454. JViewport viewport = scrollPane.getViewport();
  455. if (viewport == null || viewport.getView() != this) {
  456. return;
  457. }
  458. scrollPane.setColumnHeaderView(null);
  459. }
  460. }
  461. }
  462. //
  463. // Static Methods
  464. //
  465. /**
  466. * Equivalent to <code>new JScrollPane(aTable)</code>.
  467. *
  468. * @deprecated As of Swing version 1.0.2,
  469. * replaced by <code>new JScrollPane(aTable)</code>.
  470. */
  471. static public JScrollPane createScrollPaneForTable(JTable aTable) {
  472. return new JScrollPane(aTable);
  473. }
  474. //
  475. // Table Attributes
  476. //
  477. /**
  478. * Sets the <code>tableHeader</code> working with this <code>JTable</code> to <code>newHeader</code>.
  479. * It is legal to have a <code>null</code> <code>tableHeader</code>.
  480. *
  481. * @param tableHeader new tableHeader
  482. * @see #getTableHeader
  483. * @beaninfo
  484. * bound: true
  485. * description: The JTableHeader instance which renders the column headers.
  486. */
  487. public void setTableHeader(JTableHeader tableHeader) {
  488. if (this.tableHeader != tableHeader) {
  489. JTableHeader old = this.tableHeader;
  490. // Release the old header
  491. if (old != null) {
  492. old.setTable(null);
  493. }
  494. this.tableHeader = tableHeader;
  495. if (tableHeader != null) {
  496. tableHeader.setTable(this);
  497. }
  498. firePropertyChange("tableHeader", old, tableHeader);
  499. }
  500. }
  501. /**
  502. * Returns the <code>tableHeader</code> used by this <code>JTable</code>.
  503. *
  504. * @return the <code>tableHeader</code> used by this table
  505. * @see #setTableHeader
  506. */
  507. public JTableHeader getTableHeader() {
  508. return tableHeader;
  509. }
  510. /**
  511. * Sets the height, in pixels, of all cells to <code>rowHeight</code>,
  512. * revalidates, and repaints.
  513. * The height of the cells will be equal to the row height minus
  514. * the row margin.
  515. *
  516. * @param rowHeight new row height
  517. * @exception IllegalArgumentException if <code>rowHeight</code> is
  518. * less than 1
  519. * @see #getRowHeight
  520. * @beaninfo
  521. * bound: true
  522. * description: The height of the specified row.
  523. */
  524. public void setRowHeight(int rowHeight) {
  525. if (rowHeight <= 0) {
  526. throw new IllegalArgumentException("New row height less than 1");
  527. }
  528. int old = this.rowHeight;
  529. this.rowHeight = rowHeight;
  530. rowModel = null;
  531. resizeAndRepaint();
  532. firePropertyChange("rowHeight", old, rowHeight);
  533. }
  534. /**
  535. * Returns the height of a table row, in pixels.
  536. * The default row height is 16.0.
  537. *
  538. * @return the height in pixels of a table row
  539. * @see #setRowHeight
  540. */
  541. public int getRowHeight() {
  542. return rowHeight;
  543. }
  544. private SizeSequence getRowModel() {
  545. if (rowModel == null) {
  546. rowModel = new SizeSequence(getRowCount(), getRowHeight());
  547. }
  548. return rowModel;
  549. }
  550. /**
  551. * Sets the height for <code>row</code> to <code>rowHeight</code>,
  552. * revalidates, and repaints. The height of the cells in this row
  553. * will be equal to the row height minus the row margin.
  554. *
  555. * @param row the row whose height is being
  556. changed
  557. * @param rowHeight new row height, in pixels
  558. * @exception IllegalArgumentException if <code>rowHeight</code> is
  559. * less than 1
  560. * @beaninfo
  561. * bound: true
  562. * description: The height in pixels of the cells in <code>row</code>
  563. */
  564. public void setRowHeight(int row, int rowHeight) {
  565. if (rowHeight <= 0) {
  566. throw new IllegalArgumentException("New row height less than 1");
  567. }
  568. getRowModel().setSize(row, rowHeight);
  569. resizeAndRepaint();
  570. }
  571. /**
  572. * Returns the height, in pixels, of the cells in <code>row</code>.
  573. * @param row the row whose height is to be returned
  574. * @return the height, in pixels, of the cells in the row
  575. */
  576. public int getRowHeight(int row) {
  577. return (rowModel == null) ? getRowHeight() : rowModel.getSize(row);
  578. }
  579. /**
  580. * Sets the amount of empty space between cells in adjacent rows.
  581. *
  582. * @param rowMargin the number of pixels between cells in a row
  583. * @see #getRowMargin
  584. * @beaninfo
  585. * bound: true
  586. * description: The amount of space between cells.
  587. */
  588. public void setRowMargin(int rowMargin) {
  589. int old = this.rowMargin;
  590. this.rowMargin = rowMargin;
  591. resizeAndRepaint();
  592. firePropertyChange("rowMargin", old, rowMargin);
  593. }
  594. /**
  595. * Gets the amount of empty space, in pixels, between cells. Equivalent to:
  596. * <code>getIntercellSpacing().height</code>.
  597. * @return the number of pixels between cells in a row
  598. *
  599. * @see #setRowMargin
  600. */
  601. public int getRowMargin() {
  602. return rowMargin;
  603. }
  604. /**
  605. * Sets the <code>rowMargin</code> and the <code>columnMargin</code> --
  606. * the height and width of the space between cells -- to
  607. * <code>intercellSpacing</code>.
  608. *
  609. * @param intercellSpacing a <code>Dimension</code>
  610. * specifying the new width
  611. * and height between cells
  612. * @see #getIntercellSpacing
  613. * @beaninfo
  614. * description: The spacing between the cells,
  615. * drawn in the background color of the JTable.
  616. */
  617. public void setIntercellSpacing(Dimension intercellSpacing) {
  618. // Set the rowMargin here and columnMargin in the TableColumnModel
  619. setRowMargin(intercellSpacing.height);
  620. getColumnModel().setColumnMargin(intercellSpacing.width);
  621. resizeAndRepaint();
  622. }
  623. /**
  624. * Returns the horizontal and vertical space between cells.
  625. * The default spacing is (1, 1), which provides room to draw the grid.
  626. *
  627. * @return the horizontal and vertical spacing between cells
  628. * @see #setIntercellSpacing
  629. */
  630. public Dimension getIntercellSpacing() {
  631. return new Dimension(getColumnModel().getColumnMargin(), rowMargin);
  632. }
  633. /**
  634. * Sets the color used to draw grid lines to <code>gridColor</code> and redisplays.
  635. * The default color is look and feel dependent.
  636. *
  637. * @param gridColor the new color of the grid lines
  638. * @exception IllegalArgumentException if <code>gridColor</code> is <code>null</code>
  639. * @see #getGridColor
  640. * @beaninfo
  641. * bound: true
  642. * description: The grid color.
  643. */
  644. public void setGridColor(Color gridColor) {
  645. if (gridColor == null) {
  646. throw new IllegalArgumentException("New color is null");
  647. }
  648. Color old = this.gridColor;
  649. this.gridColor = gridColor;
  650. firePropertyChange("gridColor", old, gridColor);
  651. // Redraw
  652. repaint();
  653. }
  654. /**
  655. * Returns the color used to draw grid lines.
  656. * The default color is look and feel dependent.
  657. *
  658. * @return the color used to draw grid lines
  659. * @see #setGridColor
  660. */
  661. public Color getGridColor() {
  662. return gridColor;
  663. }
  664. /**
  665. * Sets whether the table draws grid lines around cells.
  666. * If <code>showGrid</code> is true it does; if it is false it doesn't.
  667. * There is no <code>getShowGrid</code> method as this state is held
  668. * in two variables -- <code>showHorizontalLines</code> and <code>showVerticalLines</code> --
  669. * each of which can be queried independently.
  670. *
  671. * @param showGrid true if table view should draw grid lines
  672. *
  673. * @see #setShowVerticalLines
  674. * @see #setShowHorizontalLines
  675. * @beaninfo
  676. * description: The color used to draw the grid lines.
  677. */
  678. public void setShowGrid(boolean showGrid) {
  679. setShowHorizontalLines(showGrid);
  680. setShowVerticalLines(showGrid);
  681. // Redraw
  682. repaint();
  683. }
  684. /**
  685. * Sets whether the table draws horizontal lines between cells.
  686. * If <code>showHorizontalLines</code> is true it does; if it is false it doesn't.
  687. *
  688. * @param showHorizontalLines true if table view should draw horizontal lines
  689. * @see #getShowHorizontalLines
  690. * @see #setShowGrid
  691. * @see #setShowVerticalLines
  692. * @beaninfo
  693. * bound: true
  694. * description: Whether horizontal lines should be drawn in between the cells.
  695. */
  696. public void setShowHorizontalLines(boolean showHorizontalLines) {
  697. boolean old = this.showHorizontalLines;
  698. this.showHorizontalLines = showHorizontalLines;
  699. firePropertyChange("showHorizontalLines", old, showHorizontalLines);
  700. // Redraw
  701. repaint();
  702. }
  703. /**
  704. * Sets whether the table draws vertical lines between cells.
  705. * If <code>showVerticalLines</code> is true it does; if it is false it doesn't.
  706. *
  707. * @param showVerticalLines true if table view should draw vertical lines
  708. * @see #getShowVerticalLines
  709. * @see #setShowGrid
  710. * @see #setShowHorizontalLines
  711. * @beaninfo
  712. * bound: true
  713. * description: Whether vertical lines should be drawn in between the cells.
  714. */
  715. public void setShowVerticalLines(boolean showVerticalLines) {
  716. boolean old = this.showVerticalLines;
  717. this.showVerticalLines = showVerticalLines;
  718. firePropertyChange("showVerticalLines", old, showVerticalLines);
  719. // Redraw
  720. repaint();
  721. }
  722. /**
  723. * Returns true if the table draws horizontal lines between cells, false if it
  724. * doesn't. The default is true.
  725. *
  726. * @return true if the table draws horizontal lines between cells, false if it
  727. * doesn't
  728. * @see #setShowHorizontalLines
  729. */
  730. public boolean getShowHorizontalLines() {
  731. return showHorizontalLines;
  732. }
  733. /**
  734. * Returns true if the table draws vertical lines between cells, false if it
  735. * doesn't. The default is true.
  736. *
  737. * @return true if the table draws vertical lines between cells, false if it
  738. * doesn't
  739. * @see #setShowVerticalLines
  740. */
  741. public boolean getShowVerticalLines() {
  742. return showVerticalLines;
  743. }
  744. /**
  745. * Sets the table's auto resize mode when the table is resized.
  746. *
  747. * @param mode One of 5 legal values:
  748. * AUTO_RESIZE_OFF,
  749. * AUTO_RESIZE_NEXT_COLUMN,
  750. * AUTO_RESIZE_SUBSEQUENT_COLUMNS,
  751. * AUTO_RESIZE_LAST_COLUMN,
  752. * AUTO_RESIZE_ALL_COLUMNS
  753. *
  754. * @see #getAutoResizeMode
  755. * @see #doLayout
  756. * @beaninfo
  757. * bound: true
  758. * description: Whether the columns should adjust themselves automatically.
  759. * enum: AUTO_RESIZE_OFF JTable.AUTO_RESIZE_OFF
  760. * AUTO_RESIZE_NEXT_COLUMN JTable.AUTO_RESIZE_NEXT_COLUMN
  761. * AUTO_RESIZE_SUBSEQUENT_COLUMNS JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS
  762. * AUTO_RESIZE_LAST_COLUMN JTable.AUTO_RESIZE_LAST_COLUMN
  763. * AUTO_RESIZE_ALL_COLUMNS JTable.AUTO_RESIZE_ALL_COLUMNS
  764. */
  765. public void setAutoResizeMode(int mode) {
  766. if ((mode == AUTO_RESIZE_OFF) ||
  767. (mode == AUTO_RESIZE_NEXT_COLUMN) ||
  768. (mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) ||
  769. (mode == AUTO_RESIZE_LAST_COLUMN) ||
  770. (mode == AUTO_RESIZE_ALL_COLUMNS)) {
  771. int old = autoResizeMode;
  772. autoResizeMode = mode;
  773. resizeAndRepaint();
  774. if (tableHeader != null) {
  775. tableHeader.resizeAndRepaint();
  776. }
  777. firePropertyChange("autoResizeMode", old, autoResizeMode);
  778. }
  779. }
  780. /**
  781. * Returns the auto resize mode of the table. The default mode
  782. * is AUTO_RESIZE_SUBSEQUENT_COLUMNS.
  783. *
  784. * @return the autoResizeMode of the table
  785. *
  786. * @see #setAutoResizeMode
  787. * @see #doLayout
  788. */
  789. public int getAutoResizeMode() {
  790. return autoResizeMode;
  791. }
  792. /**
  793. * Sets this table's <code>autoCreateColumnsFromModel</code> flag.
  794. * This method calls <code>createDefaultColumnsFromModel</code> if
  795. * <code>autoCreateColumnsFromModel</code> changes from false to true.
  796. *
  797. * @param autoCreateColumnsFromModel true if <code>JTable</code> should automatically create columns
  798. * @see #getAutoCreateColumnsFromModel
  799. * @see #createDefaultColumnsFromModel
  800. * @beaninfo
  801. * bound: true
  802. * description: Automatically populates the columnModel when a new TableModel is submitted.
  803. */
  804. public void setAutoCreateColumnsFromModel(boolean autoCreateColumnsFromModel) {
  805. if (this.autoCreateColumnsFromModel != autoCreateColumnsFromModel) {
  806. boolean old = this.autoCreateColumnsFromModel;
  807. this.autoCreateColumnsFromModel = autoCreateColumnsFromModel;
  808. if (autoCreateColumnsFromModel) {
  809. createDefaultColumnsFromModel();
  810. }
  811. firePropertyChange("autoCreateColumnsFromModel", old, autoCreateColumnsFromModel);
  812. }
  813. }
  814. /**
  815. * Determines whether the table will create default columns from the model.
  816. * If true, <code>setModel</code> will clear any existing columns and
  817. * create new columns from the new model. Also, if the event in
  818. * the <code>tableChanged</code> notification specifies that the
  819. * entire table changed, then the columns will be rebuilt.
  820. * The default is true.
  821. *
  822. * @return the autoCreateColumnsFromModel of the table
  823. * @see #setAutoCreateColumnsFromModel
  824. * @see #createDefaultColumnsFromModel
  825. */
  826. public boolean getAutoCreateColumnsFromModel() {
  827. return autoCreateColumnsFromModel;
  828. }
  829. /**
  830. * Creates default columns for the table from
  831. * the data model using the <code>getColumnCount</code> method
  832. * defined in the <code>TableModel</code> interface.
  833. * <p>
  834. * Clears any existing columns before creating the
  835. * new columns based on information from the model.
  836. *
  837. * @see #getAutoCreateColumnsFromModel
  838. */
  839. public void createDefaultColumnsFromModel() {
  840. TableModel m = getModel();
  841. if (m != null) {
  842. // Remove any current columns
  843. TableColumnModel cm = getColumnModel();
  844. while (cm.getColumnCount() > 0) {
  845. cm.removeColumn(cm.getColumn(0));
  846. }
  847. // Create new columns from the data model info
  848. for (int i = 0; i < m.getColumnCount(); i++) {
  849. TableColumn newColumn = new TableColumn(i);
  850. addColumn(newColumn);
  851. }
  852. }
  853. }
  854. /**
  855. * Sets a default cell renderer to be used if no renderer has been set in
  856. * a <code>TableColumn</code>. If renderer is <code>null</code>,
  857. * removes the default renderer for this column class.
  858. *
  859. * @param columnClass set the default cell renderer for this columnClass
  860. * @param renderer default cell renderer to be used for this
  861. * columnClass
  862. * @see #getDefaultRenderer
  863. * @see #setDefaultEditor
  864. */
  865. public void setDefaultRenderer(Class columnClass, TableCellRenderer renderer) {
  866. if (renderer != null) {
  867. defaultRenderersByColumnClass.put(columnClass, renderer);
  868. }
  869. else {
  870. defaultRenderersByColumnClass.remove(columnClass);
  871. }
  872. }
  873. /**
  874. * Returns the cell renderer to be used when no renderer has been set in
  875. * a <code>TableColumn</code>. During the rendering of cells the renderer is fetched from
  876. * a <code>Hashtable</code> of entries according to the class of the cells in the column. If
  877. * there is no entry for this <code>columnClass</code> the method returns
  878. * the entry for the most specific superclass. The <code>JTable</code> installs entries
  879. * for <code>Object</code>, <code>Number</code>, and <code>Boolean</code>, all of which can be modified
  880. * or replaced.
  881. *
  882. * @param columnClass return the default cell renderer
  883. * for this columnClass
  884. * @return the renderer for this columnClass
  885. * @see #setDefaultRenderer
  886. * @see #getColumnClass
  887. */
  888. public TableCellRenderer getDefaultRenderer(Class columnClass) {
  889. if (columnClass == null) {
  890. return null;
  891. }
  892. else {
  893. Object renderer = defaultRenderersByColumnClass.get(columnClass);
  894. if (renderer != null) {
  895. return (TableCellRenderer)renderer;
  896. }
  897. else {
  898. return getDefaultRenderer(columnClass.getSuperclass());
  899. }
  900. }
  901. }
  902. /**
  903. * Sets a default cell editor to be used if no editor has been set in
  904. * a <code>TableColumn</code>. If no editing is required in a table, or a
  905. * particular column in a table, uses the <code>isCellEditable</code>
  906. * method in the <code>TableModel</code> interface to ensure that this
  907. * <code>JTable</code> will not start an editor in these columns.
  908. * If editor is <code>null</code>, removes the default editor for this
  909. * column class.
  910. *
  911. * @param columnClass set the default cell editor for this columnClass
  912. * @param editor default cell editor to be used for this columnClass
  913. * @see TableModel#isCellEditable
  914. * @see #getDefaultEditor
  915. * @see #setDefaultRenderer
  916. */
  917. public void setDefaultEditor(Class columnClass, TableCellEditor editor) {
  918. if (editor != null) {
  919. defaultEditorsByColumnClass.put(columnClass, editor);
  920. }
  921. else {
  922. defaultEditorsByColumnClass.remove(columnClass);
  923. }
  924. }
  925. /**
  926. * Returns the editor to be used when no editor has been set in
  927. * a <code>TableColumn</code>. During the editing of cells the editor is fetched from
  928. * a <code>Hashtable</code> of entries according to the class of the cells in the column. If
  929. * there is no entry for this <code>columnClass</code> the method returns
  930. * the entry for the most specific superclass. The <code>JTable</code> installs entries
  931. * for <code>Object</code>, <code>Number</code>, and <code>Boolean</code>, all of which can be modified
  932. * or replaced.
  933. *
  934. * @param columnClass return the default cell editor for this columnClass
  935. * @return the default cell editor to be used for this columnClass
  936. * @see #setDefaultEditor
  937. * @see #getColumnClass
  938. */
  939. public TableCellEditor getDefaultEditor(Class columnClass) {
  940. if (columnClass == null) {
  941. return null;
  942. }
  943. else {
  944. Object editor = defaultEditorsByColumnClass.get(columnClass);
  945. if (editor != null) {
  946. return (TableCellEditor)editor;
  947. }
  948. else {
  949. return getDefaultEditor(columnClass.getSuperclass());
  950. }
  951. }
  952. }
  953. /**
  954. * Sets the <code>dragEnabled</code> property,
  955. * which must be <code>true</code> to enable
  956. * automatic drag handling (the first part of drag and drop)
  957. * on this component.
  958. * The <code>transferHandler</code> property needs to be set
  959. * to a non-<code>null</code> value for the drag to do
  960. * anything. The default value of the <code>dragEnabled</code
  961. * property
  962. * is <code>false</code>.
  963. *
  964. * <p>
  965. *
  966. * When automatic drag handling is enabled,
  967. * most look and feels begin a drag-and-drop operation
  968. * whenever the user presses the mouse button over a selection
  969. * and then moves the mouse a few pixels.
  970. * Setting this property to <code>true</code>
  971. * can therefore have a subtle effect on
  972. * how selections behave.
  973. *
  974. * <p>
  975. *
  976. * Some look and feels might not support automatic drag and drop;
  977. * they will ignore this property. You can work around such
  978. * look and feels by modifying the component
  979. * to directly call the <code>exportAsDrag</code> method of a
  980. * <code>TransferHandler</code>.
  981. *
  982. * @param b the value to set the <code>dragEnabled</code> property to
  983. * @exception HeadlessException if
  984. * <code>b</code> is <code>true</code> and
  985. * <code>GraphicsEnvironment.isHeadless()</code>
  986. * returns <code>true</code>
  987. * @see java.awt.GraphicsEnvironment#isHeadless
  988. * @see #getDragEnabled
  989. * @see #setTransferHandler
  990. * @see TransferHandler
  991. * @since 1.4
  992. *
  993. * @beaninfo
  994. * description: determines whether automatic drag handling is enabled
  995. * bound: false
  996. */
  997. public void setDragEnabled(boolean b) {
  998. if (b && GraphicsEnvironment.isHeadless()) {
  999. throw new HeadlessException();
  1000. }
  1001. dragEnabled = b;
  1002. }
  1003. /**
  1004. * Gets the value of the <code>dragEnabled</code> property.
  1005. *
  1006. * @return the value of the <code>dragEnabled</code> property
  1007. * @see #setDragEnabled
  1008. * @since 1.4
  1009. */
  1010. public boolean getDragEnabled() {
  1011. return dragEnabled;
  1012. }
  1013. //
  1014. // Selection methods
  1015. //
  1016. /**
  1017. * Sets the table's selection mode to allow only single selections, a single
  1018. * contiguous interval, or multiple intervals.
  1019. * <P>
  1020. * <bold>Note:</bold>
  1021. * <code>JTable</code> provides all the methods for handling
  1022. * column and row selection. When setting states,
  1023. * such as <code>setSelectionMode</code>, it not only
  1024. * updates the mode for the row selection model but also sets similar
  1025. * values in the selection model of the <code>columnModel</code>.
  1026. * If you want to have the row and column selection models operating
  1027. * in different modes, set them both directly.
  1028. * <p>
  1029. * Both the row and column selection models for <code>JTable</code>
  1030. * default to using a <code>DefaultListSelectionModel</code>
  1031. * so that <code>JTable</code> works the same way as the
  1032. * <code>JList</code>. See the <code>setSelectionMode</code> method
  1033. * in <code>JList</code> for details about the modes.
  1034. *
  1035. * @see JList#setSelectionMode
  1036. * @beaninfo
  1037. * description: The selection mode used by the row and column selection models.
  1038. * enum: SINGLE_SELECTION ListSelectionModel.SINGLE_SELECTION
  1039. * SINGLE_INTERVAL_SELECTION ListSelectionModel.SINGLE_INTERVAL_SELECTION
  1040. * MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
  1041. */
  1042. public void setSelectionMode(int selectionMode) {
  1043. clearSelection();
  1044. getSelectionModel().setSelectionMode(selectionMode);
  1045. getColumnModel().getSelectionModel().setSelectionMode(selectionMode);
  1046. }
  1047. /**
  1048. * Sets whether the rows in this model can be selected.
  1049. *
  1050. * @param rowSelectionAllowed true if this model will allow row selection
  1051. * @see #getRowSelectionAllowed
  1052. * @beaninfo
  1053. * bound: true
  1054. * attribute: visualUpdate true
  1055. * description: If true, an entire row is selected for each selected cell.
  1056. */
  1057. public void setRowSelectionAllowed(boolean rowSelectionAllowed) {
  1058. boolean old = this.rowSelectionAllowed;
  1059. this.rowSelectionAllowed = rowSelectionAllowed;
  1060. if (old != rowSelectionAllowed) {
  1061. repaint();
  1062. }
  1063. firePropertyChange("rowSelectionAllowed", old, rowSelectionAllowed);
  1064. }
  1065. /**
  1066. * Returns true if rows can be selected.
  1067. *
  1068. * @return true if rows can be selected, otherwise false
  1069. * @see #setRowSelectionAllowed
  1070. */
  1071. public boolean getRowSelectionAllowed() {
  1072. return rowSelectionAllowed;
  1073. }
  1074. /**
  1075. * Sets whether the columns in this model can be selected.
  1076. *
  1077. * @param columnSelectionAllowed true if this model will allow column selection
  1078. * @see #getColumnSelectionAllowed
  1079. * @beaninfo
  1080. * bound: true
  1081. * attribute: visualUpdate true
  1082. * description: If true, an entire column is selected for each selected cell.
  1083. */
  1084. public void setColumnSelectionAllowed(boolean columnSelectionAllowed) {
  1085. boolean old = columnModel.getColumnSelectionAllowed();
  1086. columnModel.setColumnSelectionAllowed(columnSelectionAllowed);
  1087. if (old != columnSelectionAllowed) {
  1088. repaint();
  1089. }
  1090. firePropertyChange("columnSelectionAllowed", old, columnSelectionAllowed);
  1091. }
  1092. /**
  1093. * Returns true if columns can be selected.
  1094. *
  1095. * @return true if columns can be selected, otherwise false
  1096. * @see #setColumnSelectionAllowed
  1097. */
  1098. public boolean getColumnSelectionAllowed() {
  1099. return columnModel.getColumnSelectionAllowed();
  1100. }
  1101. /**
  1102. * Sets whether this table allows both a column selection and a
  1103. * row selection to exist simultaneously. When set,
  1104. * the table treats the intersection of the row and column selection
  1105. * models as the selected cells. Override <code>isCellSelected</code> to
  1106. * change this default behavior. This method is equivalent to setting
  1107. * both the <code>rowSelectionAllowed</code> property and
  1108. * <code>columnSelectionAllowed</code> property of the
  1109. * <code>columnModel</code> to the supplied value.
  1110. *
  1111. * @param cellSelectionEnabled true if simultaneous row and column
  1112. * selection is allowed
  1113. * @see #getCellSelectionEnabled
  1114. * @see #isCellSelected
  1115. * @beaninfo
  1116. * bound: true
  1117. * attribute: visualUpdate true
  1118. * description: Select a rectangular region of cells rather than
  1119. * rows or columns.
  1120. */
  1121. public void setCellSelectionEnabled(boolean cellSelectionEnabled) {
  1122. setRowSelectionAllowed(cellSelectionEnabled);
  1123. setColumnSelectionAllowed(cellSelectionEnabled);
  1124. boolean old = this.cellSelectionEnabled;
  1125. this.cellSelectionEnabled = cellSelectionEnabled;
  1126. firePropertyChange("cellSelectionEnabled", old, cellSelectionEnabled);
  1127. }
  1128. /**
  1129. * Returns true if both row and column selection models are enabled.
  1130. * Equivalent to <code>getRowSelectionAllowed() &&
  1131. * getColumnSelectionAllowed()</code>.
  1132. *
  1133. * @return true if both row and column selection models are enabled
  1134. *
  1135. * @see #setCellSelectionEnabled
  1136. */
  1137. public boolean getCellSelectionEnabled() {
  1138. return getRowSelectionAllowed() && getColumnSelectionAllowed();
  1139. }
  1140. /**
  1141. * Selects all rows, columns, and cells in the table.
  1142. */
  1143. public void selectAll() {
  1144. // If I'm currently editing, then I should stop editing
  1145. if (isEditing()) {
  1146. removeEditor();
  1147. }
  1148. if (getRowCount() > 0 && getColumnCount() > 0) {
  1149. setRowSelectionInterval(0, getRowCount()-1);
  1150. setColumnSelectionInterval(0, getColumnCount()-1);
  1151. }
  1152. }
  1153. /**
  1154. * Deselects all selected columns and rows.
  1155. */
  1156. public void clearSelection() {
  1157. columnModel.getSelectionModel().clearSelection();
  1158. selectionModel.clearSelection();
  1159. }
  1160. private int boundRow(int row) throws IllegalArgumentException {
  1161. if (row < 0 || row >= getRowCount()) {
  1162. throw new IllegalArgumentException("Row index out of range");
  1163. }
  1164. return row;
  1165. }
  1166. private int boundColumn(int col) {
  1167. if (col< 0 || col >= getColumnCount()) {
  1168. throw new IllegalArgumentException("Column index out of range");
  1169. }
  1170. return col;
  1171. }
  1172. /**
  1173. * Selects the rows from <code>index0</code> to <code>index1</code>,
  1174. * inclusive.
  1175. *
  1176. * @exception IllegalArgumentException if <code>index0</code> or
  1177. * <code>index1</code> lie outside
  1178. * [0, <code>getRowCount()</code>-1]
  1179. * @param index0 one end of the interval
  1180. * @param index1 the other end of the interval
  1181. */
  1182. public void setRowSelectionInterval(int index0, int index1) {
  1183. selectionModel.setSelectionInterval(boundRow(index0), boundRow(index1));
  1184. }
  1185. /**
  1186. * Selects the columns from <code>index0</code> to <code>index1</code>,
  1187. * inclusive.
  1188. *
  1189. * @exception IllegalArgumentException if <code>index0</code> or
  1190. * <code>index1</code> lie outside
  1191. * [0, <code>getColumnCount()</code>-1]
  1192. * @param index0 one end of the interval
  1193. * @param index1 the other end of the interval
  1194. */
  1195. public void setColumnSelectionInterval(int index0, int index1) {
  1196. columnModel.getSelectionModel().setSelectionInterval(boundColumn(index0), boundColumn(index1));
  1197. }
  1198. /**
  1199. * Adds the rows from <code>index0</code> to <code>index1</code>, inclusive, to
  1200. * the current selection.
  1201. *
  1202. * @exception IllegalArgumentException if <code>index0</code> or <code>index1</code>
  1203. * lie outside [0, <code>getRowCount()</code>-1]
  1204. * @param index0 one end of the interval
  1205. * @param index1 the other end of the interval
  1206. */
  1207. public void addRowSelectionInterval(int index0, int index1) {
  1208. selectionModel.addSelectionInterval(boundRow(index0), boundRow(index1));
  1209. }
  1210. /**
  1211. * Adds the columns from <code>index0</code> to <code>index1</code>,
  1212. * inclusive, to the current selection.
  1213. *
  1214. * @exception IllegalArgumentException if <code>index0</code> or
  1215. * <code>index1</code> lie outside
  1216. * [0, <code>getColumnCount()</code>-1]
  1217. * @param index0 one end of the interval
  1218. * @param index1 the other end of the interval
  1219. */
  1220. public void addColumnSelectionInterval(int index0, int index1) {
  1221. columnModel.getSelectionModel().addSelectionInterval(boundColumn(index0), boundColumn(index1));
  1222. }
  1223. /**
  1224. * Deselects the rows from <code>index0</code> to <code>index1</code>, inclusive.
  1225. *
  1226. * @exception IllegalArgumentException if <code>index0</code> or
  1227. * <code>index1</code> lie outside
  1228. * [0, <code>getRowCount()</code>-1]
  1229. * @param index0 one end of the interval
  1230. * @param index1 the other end of the interval
  1231. */
  1232. public void removeRowSelectionInterval(int index0, int index1) {
  1233. selectionModel.removeSelectionInterval(boundRow(index0), boundRow(index1));
  1234. }
  1235. /**
  1236. * Deselects the columns from <code>index0</code> to <code>index1</code>, inclusive.
  1237. *
  1238. * @exception IllegalArgumentException if <code>index0</code> or
  1239. * <code>index1</code> lie outside
  1240. * [0, <code>getColumnCount()</code>-1]
  1241. * @param index0 one end of the interval
  1242. * @param index1 the other end of the interval
  1243. */
  1244. public void removeColumnSelectionInterval(int index0, int index1) {
  1245. columnModel.getSelectionModel().removeSelectionInterval(boundColumn(index0), boundColumn(index1));
  1246. }
  1247. /**
  1248. * Returns the index of the first selected row, -1 if no row is selected.
  1249. * @return the index of the first selected row
  1250. */
  1251. public int getSelectedRow() {
  1252. return selectionModel.getMinSelectionIndex();
  1253. }
  1254. /**
  1255. * Returns the index of the first selected column,
  1256. * -1 if no column is selected.
  1257. * @return the index of the first selected column
  1258. */
  1259. public int getSelectedColumn() {
  1260. return columnModel.getSelectionModel().getMinSelectionIndex();
  1261. }
  1262. /**
  1263. * Returns the indices of all selected rows.
  1264. *
  1265. * @return an array of integers containing the indices of all selected rows,
  1266. * or an empty array if no row is selected
  1267. * @see #getSelectedRow
  1268. */
  1269. public int[] getSelectedRows() {
  1270. int iMin = selectionModel.getMinSelectionIndex();
  1271. int iMax = selectionModel.getMaxSelectionIndex();
  1272. if ((iMin == -1) || (iMax == -1)) {
  1273. return new int[0];
  1274. }
  1275. int[] rvTmp = new int[1+ (iMax - iMin)];
  1276. int n = 0;
  1277. for(int i = iMin; i <= iMax; i++) {
  1278. if (selectionModel.isSelectedIndex(i)) {
  1279. rvTmp[n++] = i;
  1280. }
  1281. }
  1282. int[] rv = new int[n];
  1283. System.arraycopy(rvTmp, 0, rv, 0, n);
  1284. return rv;
  1285. }