1. /*
  2. * @(#)JTable.java 1.121 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.util.*;
  9. import java.awt.*;
  10. import java.awt.event.*;
  11. import java.beans.*;
  12. import java.io.Serializable;
  13. import java.io.ObjectOutputStream;
  14. import java.io.ObjectInputStream;
  15. import java.io.IOException;
  16. import javax.accessibility.*;
  17. import javax.swing.event.*;
  18. import javax.swing.plaf.*;
  19. import javax.swing.table.*;
  20. import javax.swing.border.*;
  21. import java.text.DateFormat;
  22. import java.text.NumberFormat;
  23. /**
  24. * JTable is a user-interface component that presents data in a two-dimensional
  25. * table format. The JTable has many facilities that make it possible to
  26. * customize its rendering and editing but provides defaults
  27. * for these features so that simple tables can be set up easily.
  28. * For example, to set up a table with 10 rows and 10 columns of numbers:
  29. * <p>
  30. * <pre>
  31. * TableModel dataModel = new AbstractTableModel() {
  32. * public int getColumnCount() { return 10; }
  33. * public int getRowCount() { return 10;}
  34. * public Object getValueAt(int row, int col) { return new Integer(row*col); }
  35. * };
  36. * JTable table = new JTable(dataModel);
  37. * JScrollPane scrollpane = new JScrollPane(table);
  38. * </pre>
  39. * <p>
  40. * Because the JTable is now much easier to set up with custom models
  41. * the DefaultTableModel is less useful than it was in previous releases.
  42. * Instead of copying the data in an application into the DefaultTableModel,
  43. * we recommend wrapping it in the methods of the TableModel interface and
  44. * passing the real data to the JTable as above. This technique is nearly as concise
  45. * as using a DefaultTableModel and starting this way has a number of advantages
  46. * over the longer term. In particular: it is a scalable technique,
  47. * is easier to handle dynamic or editable tables and often results in much
  48. * more efficient applications because the model is free to choose the
  49. * internal representation that best suits the data.
  50. * <p>
  51. * The "Table" directory in the examples/demo area gives a number of complete
  52. * examples of JTable usage, covering how the JTable can be used to provide
  53. * an editable view of data taken from a database and how to modify the columns
  54. * in the display to use specialized renderers and editors. For example, overriding
  55. * AbstractTableModel's <code>getColumnClass()</code> method to return a value of
  56. * <code>ImageIcon.class</code> for a given column allows icons to be displayed,
  57. * while returning a value of <code>Number.class</code> allows digits to be
  58. * right-justified in the column.
  59. * <p>
  60. * The JTable uses integers exclusively to refer to both the rows and the columns
  61. * of the model that it displays. The JTable simply takes a tabular range of cells
  62. * and uses <code>getValueAt(int, int)</code> to retrieve and display the appropriate
  63. * values from the model.
  64. * <p>
  65. * If <code>getTableHeader().setReorderingAllowed(boolean)</code> is used to
  66. * enable column reordering columns may be rearranged in the JTable so that the
  67. * view's columns appear in a different order to the columns in the model.
  68. * This does not affect the implementation of the model at all: when the
  69. * columns are reordered, the JTable maintains the new order of the columns
  70. * internally and converts its column indices before querying the model.
  71. * <p>
  72. * So, when writing a TableModel, it is not necessary to listen for column
  73. * reordering events as the the model will be queried in its own co-ordinate
  74. * system regardless of what is happening in the view.
  75. * In the examples area there is a demonstration of a sorting algorithm making
  76. * use of exactly this technique to interpose yet another co-ordinate system
  77. * where the order of the rows is changed, rather than the order of the columns.
  78. * <p>
  79. * The general rule for the JTable API and the APIs of all its associated classes,
  80. * including the the column model and both the row and column selection models, is:
  81. * methods using integer indices for rows and columns always use the co-ordinate
  82. * system of the view. There are three exceptions to this rule:
  83. * <ul>
  84. * <li> All references to rows and columns in the TableModel
  85. * interface are in the co-ordinate system of the model.
  86. * <li> The index <I>modelIndex</I> in the TableColumn constructors
  87. * refers to the index of the column in the model, not the view.
  88. * <li> All constructors for the TableModelEvent, which describes changes
  89. * that have taken place in a table model, use the co-ordinate system
  90. * of the model.
  91. * </ul>
  92. * The TableColumn provides a slot for holding an identifier or "tag" for each column
  93. * and the JTable and TableColumModel both support <I>getColumn(Object id)</I>
  94. * conveniences for locating columns by their identifier. If no identifier is
  95. * explicitly set, the TableColumn returns its header value (the name of the column)
  96. * as a default. A different identifier, which can be of any type, can be set
  97. * using the TableColumn's <I>setIdentifier()</I> method. All of the JTable's
  98. * functions operate correctly regardless of the type and uniqueness of these
  99. * identifiers.
  100. * <p>
  101. * The <I>convertColumnIndexToView()</I> and
  102. * <I>convertColumnIndexToModel()</I> methods have been provided to
  103. * convert between the two co-ordinate systems but
  104. * they are rarely needed during normal use.
  105. * <p>
  106. * Like all JComponent classes, you can use
  107. * {@link JComponent#registerKeyboardAction} to associate an
  108. * {@link Action} object with a {@link KeyStroke} and execute the
  109. * action under specified conditions.
  110. * <p>
  111. * See <a href="http://java.sun.com/docs/books/tutorial/ui/swing/table.html">How to Use Tables</a>
  112. * in <a href="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
  113. * for further documentation.
  114. * <p>
  115. * For the keyboard keys used by this component in the standard Look and
  116. * Feel (L&F) renditions, see the
  117. * <a href="doc-files/Key-Index.html#JTable">JTable</a> key assignments.
  118. * <p>
  119. * <strong>Warning:</strong>
  120. * Serialized objects of this class will not be compatible with
  121. * future Swing releases. The current serialization support is appropriate
  122. * for short term storage or RMI between applications running the same
  123. * version of Swing. A future release of Swing will provide support for
  124. * long term persistence.
  125. *
  126. *
  127. * @beaninfo
  128. * attribute: isContainer false
  129. *
  130. * @version 1.121 11/29/01
  131. * @author Philip Milne
  132. * @author Alan Chung
  133. */
  134. public class JTable extends JComponent implements TableModelListener, Scrollable,
  135. TableColumnModelListener, ListSelectionListener, CellEditorListener,
  136. Accessible
  137. {
  138. //
  139. // Static Constants
  140. //
  141. /**
  142. * @see #getUIClassID
  143. * @see #readObject
  144. */
  145. private static final String uiClassID = "TableUI";
  146. /** Do not adjust column widths automatically, use a scrollbar */
  147. public static final int AUTO_RESIZE_OFF = 0;
  148. /** When a column is adjusted in the UI, adjust the next column the opposite way */
  149. public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
  150. /** During UI adjustment, change subsequent columns to preserve the total width */
  151. public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
  152. /** During all resize operations, apply adjustments to the last column only */
  153. public static final int AUTO_RESIZE_LAST_COLUMN = 3;
  154. /** During all resize operations, proportionately resize all columns */
  155. public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
  156. //
  157. // Instance Variables
  158. //
  159. /** The TableModel of the table */
  160. protected TableModel dataModel;
  161. /** The TableColumnModel of the table */
  162. protected TableColumnModel columnModel;
  163. /** The ListSelectionModel of the table, used to keep track of row selections */
  164. protected ListSelectionModel selectionModel;
  165. /** The TableHeader working with the table */
  166. protected JTableHeader tableHeader;
  167. /** The height of all rows in the table */
  168. protected int rowHeight;
  169. /** The height margin between rows */
  170. protected int rowMargin;
  171. /** The color of the grid */
  172. protected Color gridColor;
  173. /** The table draws horizontal lines between cells if showHorizontalLines is true */
  174. protected boolean showHorizontalLines;
  175. /** The table draws vertical lines between cells if showVerticalLines is true */
  176. protected boolean showVerticalLines;
  177. /**
  178. * This mode value determines if table automatically resizes the
  179. * width the table's columns to take up the entire width of the
  180. * table, and how it does the resizing.
  181. */
  182. protected int autoResizeMode;
  183. /**
  184. * The table will query the TableModel to build the default
  185. * set of columns if this is true.
  186. */
  187. protected boolean autoCreateColumnsFromModel;
  188. /** Used by the Scrollable interface to determine the initial visible area */
  189. protected Dimension preferredViewportSize;
  190. /** Row selection allowed in this table */
  191. protected boolean rowSelectionAllowed;
  192. /**
  193. * If this is true, then both a row selection and a column selection
  194. * can be non-empty at the same time, the selected cells are the
  195. * the cells whose row and column are both selected.
  196. */
  197. protected boolean cellSelectionEnabled;
  198. /** If editing, Component that is handling the editing. */
  199. transient protected Component editorComp;
  200. /**
  201. * The object that overwrites the screen real estate occupied by the
  202. * current cell and allows the user to change those contents.
  203. */
  204. transient protected TableCellEditor cellEditor;
  205. /** Identifies the column of the cell being edited. */
  206. transient protected int editingColumn;
  207. /** Identifies the row of the cell being edited. */
  208. transient protected int editingRow;
  209. /**
  210. * A table of objects that display the contents of a cell,
  211. * indexed by class.
  212. */
  213. transient protected Hashtable defaultRenderersByColumnClass;
  214. /**
  215. * A table of objects that display and edit the contents of a cell,
  216. * indexed by class.
  217. */
  218. transient protected Hashtable defaultEditorsByColumnClass;
  219. /** The foreground color of selected cells */
  220. protected Color selectionForeground;
  221. /** The background color of selected cells */
  222. protected Color selectionBackground;
  223. //
  224. // Constructors
  225. //
  226. /**
  227. * Constructs a default JTable which is initialized with a default
  228. * data model, a default column model, and a default selection
  229. * model.
  230. *
  231. * @see #createDefaultDataModel
  232. * @see #createDefaultColumnModel
  233. * @see #createDefaultSelectionModel
  234. */
  235. public JTable() {
  236. this(null, null, null);
  237. }
  238. /**
  239. * Constructs a JTable which is initialized with <i>dm</i> as the
  240. * data model, a default column model, and a default selection
  241. * model.
  242. *
  243. * @param dm The data model for the table
  244. * @see #createDefaultColumnModel
  245. * @see #createDefaultSelectionModel
  246. */
  247. public JTable(TableModel dm) {
  248. this(dm, null, null);
  249. }
  250. /**
  251. * Constructs a JTable which is initialized with <i>dm</i> as the
  252. * data model, <i>cm</i> as the column model, and a default selection
  253. * model.
  254. *
  255. * @param dm The data model for the table
  256. * @param cm The column model for the table
  257. * @see #createDefaultSelectionModel
  258. */
  259. public JTable(TableModel dm, TableColumnModel cm) {
  260. this(dm, cm, null);
  261. }
  262. /**
  263. * Constructs a JTable which is initialized with <i>dm</i> as the
  264. * data model, <i>cm</i> as the column model, and <i>sm</i> as the
  265. * selection model. If any of the parameters are <b>null</b> this
  266. * method will initialize the table with the corresponding
  267. * default model. The <i>autoCreateColumnsFromModel</i> flag is set
  268. * to false if <i>cm</i> is non-null, otherwise it is set to true
  269. * and the column model is populated with suitable TableColumns
  270. * for the columns in <i>dm</i>.
  271. *
  272. * @param dm The data model for the table
  273. * @param cm The column model for the table
  274. * @param sm The row selection model for the table
  275. * @see #createDefaultDataModel
  276. * @see #createDefaultColumnModel
  277. * @see #createDefaultSelectionModel
  278. */
  279. public JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
  280. super();
  281. setLayout(null);
  282. if (cm == null) {
  283. cm = createDefaultColumnModel();
  284. autoCreateColumnsFromModel = true;
  285. }
  286. setColumnModel(cm);
  287. if (sm == null)
  288. sm = createDefaultSelectionModel();
  289. setSelectionModel(sm);
  290. // Set the model last, that way if the autoCreatColumnsFromModel has
  291. // been set above, we will automatically populate an empty columnModel
  292. // with suitable columns for the new model.
  293. if (dm == null)
  294. dm = createDefaultDataModel();
  295. setModel(dm);
  296. initializeLocalVars();
  297. updateUI();
  298. }
  299. /**
  300. * Constructs a JTable with <i>numRows</i> and <i>numColumns</i> of
  301. * empty cells using the DefaultTableModel. The columns will have
  302. * names of the form "A", "B", "C", etc.
  303. *
  304. * @param numRows The number of rows the table holds
  305. * @param numColumns The number of columns the table holds
  306. * @see javax.swing.table.DefaultTableModel
  307. */
  308. public JTable(int numRows, int numColumns) {
  309. this(new DefaultTableModel(numRows, numColumns));
  310. }
  311. /**
  312. * Constructs a JTable to display the values in the Vector of Vectors,
  313. * <i>rowData</i>, with column names, <i>columnNames</i>.
  314. * The Vectors contained in <i>rowData</i> should contain the values
  315. * for that row. In other words, the value of the cell at row 1,
  316. * column 5 can be obtained with the following code:
  317. * <p>
  318. * <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre>
  319. * <p>
  320. * All rows must be of the same length as <i>columnNames</i>.
  321. * <p>
  322. * @param rowData The data for the new table
  323. * @param columnNames Names of each column
  324. */
  325. public JTable(final Vector rowData, final Vector columnNames) {
  326. this(new AbstractTableModel() {
  327. public String getColumnName(int column) { return columnNames.elementAt(column).toString(); }
  328. public int getRowCount() { return rowData.size(); }
  329. public int getColumnCount() { return columnNames.size(); }
  330. public Object getValueAt(int row, int column) {
  331. return ((Vector)rowData.elementAt(row)).elementAt(column);
  332. }
  333. public boolean isCellEditable(int row, int column) { return true; }
  334. public void setValueAt(Object value, int row, int column) {
  335. ((Vector)rowData.elementAt(row)).setElementAt(value, column);
  336. fireTableCellUpdated(row, column);
  337. }
  338. });
  339. }
  340. /**
  341. * Constructs a JTable to display the values in the two dimensional array,
  342. * <i>rowData</i>, with column names, <i>columnNames</i>.
  343. * <i>rowData</i> is an Array of rows, so the value of the cell at row 1,
  344. * column 5 can be obtained with the following code:
  345. * <p>
  346. * <pre> rowData[1][5]; </pre>
  347. * <p>
  348. * All rows must be of the same length as <i>columnNames</i>.
  349. * <p>
  350. * @param rowData The data for the new table
  351. * @param columnNames Names of each column
  352. */
  353. public JTable(final Object[][] rowData, final Object[] columnNames) {
  354. this(new AbstractTableModel() {
  355. public String getColumnName(int column) { return columnNames[column].toString(); }
  356. public int getRowCount() { return rowData.length; }
  357. public int getColumnCount() { return columnNames.length; }
  358. public Object getValueAt(int row, int col) { return rowData[row][col]; }
  359. public boolean isCellEditable(int row, int column) { return true; }
  360. public void setValueAt(Object value, int row, int col) {
  361. rowData[row][col] = value;
  362. fireTableCellUpdated(row, col);
  363. }
  364. });
  365. }
  366. /**
  367. * Calls <code>configureEnclosingScrollPane</code>.
  368. *
  369. * @see #configureEnclosingScrollPane
  370. */
  371. public void addNotify() {
  372. super.addNotify();
  373. configureEnclosingScrollPane();
  374. }
  375. /**
  376. * If the JTable is the viewportView of an enclosing JScrollPane
  377. * (the usual situation), configure this ScrollPane by, amongst other things,
  378. * installing the table's tableHeader as the columnHeaderView of the scrollpane.
  379. * When a JTable is added to a JScrollPane in the usual way,
  380. * using <code>new JScrollPane(myTable)</code>, <code>addNotify</code> is
  381. * called in the JTable (when the table is added to the viewport).
  382. * JTable's <code>addNotify</code> method in turn calls this method
  383. * which is protected so that this default installation procedure can
  384. * be overridden by a subclass.
  385. *
  386. * @see #addNotify
  387. */
  388. protected void configureEnclosingScrollPane() {
  389. Container p = getParent();
  390. if (p instanceof JViewport) {
  391. Container gp = p.getParent();
  392. if (gp instanceof JScrollPane) {
  393. JScrollPane scrollPane = (JScrollPane)gp;
  394. // Make certain we are the viewPort's view and not, for
  395. // example, the rowHeaderView of the scrollPane -
  396. // an implementor of fixed columns might do this.
  397. JViewport viewport = scrollPane.getViewport();
  398. if (viewport == null || viewport.getView() != this) {
  399. return;
  400. }
  401. scrollPane.setColumnHeaderView(getTableHeader());
  402. scrollPane.getViewport().setBackingStoreEnabled(true);
  403. Border border = scrollPane.getBorder();
  404. if (border == null || border instanceof UIResource) {
  405. scrollPane.setBorder(UIManager.getBorder("Table.scrollPaneBorder"));
  406. }
  407. }
  408. }
  409. }
  410. //
  411. // Static Methods
  412. //
  413. /**
  414. * Equivalent to <code>new JScrollPane(aTable)</code>.
  415. *
  416. * @deprecated As of Swing version 1.0.2,
  417. * replaced by <code>new JScrollPane(aTable)</code>.
  418. */
  419. static public JScrollPane createScrollPaneForTable(JTable aTable) {
  420. return new JScrollPane(aTable);
  421. }
  422. //
  423. // Table Attributes
  424. //
  425. /**
  426. * Sets the tableHeader working with this JTable to <I>newHeader</I>.
  427. * It is legal to have a <B>null</B> tableHeader.
  428. *
  429. * @param newHeader new tableHeader
  430. * @see #getTableHeader
  431. * @beaninfo
  432. * description: The JTableHeader instance which renders the column headers.
  433. */
  434. public void setTableHeader(JTableHeader newHeader) {
  435. if (tableHeader != newHeader) {
  436. // Release the old header
  437. if (tableHeader != null)
  438. tableHeader.setTable(null);
  439. tableHeader = newHeader;
  440. if (tableHeader != null)
  441. tableHeader.setTable(this);
  442. }
  443. }
  444. /**
  445. * Returns the tableHeader working with this JTable.
  446. *
  447. * @return the tableHeader working with the receiver
  448. * @see #setTableHeader
  449. */
  450. public JTableHeader getTableHeader() {
  451. return tableHeader;
  452. }
  453. /**
  454. * Sets the height for rows to <I>newRowHeight</I> and invokes tile
  455. *
  456. * @param newRowHeight new row height
  457. * @exception IllegalArgumentException If <I>newRowHeight</I> is
  458. * less than 1.
  459. * @see #getRowHeight
  460. * @beaninfo
  461. * description: The height of the cells including the inter-cell spacing.
  462. */
  463. public void setRowHeight(int newHeight) {
  464. if (newHeight <= 0) {
  465. throw new IllegalArgumentException("New row height less than 1");
  466. }
  467. rowHeight = newHeight;
  468. resizeAndRepaint();
  469. }
  470. /**
  471. * Returns the height of a table row in the receiver.
  472. * The default row height is 16.0.
  473. *
  474. * @return the height of each row in the receiver
  475. * @see #setRowHeight
  476. */
  477. public int getRowHeight() {
  478. return rowHeight;
  479. }
  480. /**
  481. * Sets the amount of emtpy space between rows.
  482. *
  483. * @see #getRowMargin
  484. */
  485. public void setRowMargin(int rowMargin) {
  486. this.rowMargin = rowMargin;
  487. }
  488. /**
  489. * Gets the amount of emtpy space between rows. Equivalent to:
  490. * <code>getIntercellSpacing().height</code>.
  491. *
  492. * @see #setRowMargin
  493. */
  494. public int getRowMargin() {
  495. return rowMargin;
  496. }
  497. /**
  498. * Sets the width and height between cells to <I>newSpacing</I> and
  499. * redisplays the receiver.
  500. *
  501. * @param newSpacing The new width and height intercellSpacing
  502. * @see #getIntercellSpacing
  503. * @beaninfo
  504. * description: The spacing between the cells, drawn in the background color of the JTable.
  505. */
  506. public void setIntercellSpacing(Dimension newSpacing) {
  507. // Set the rowMargin here and columnMargin in the TableColumnModel
  508. rowMargin = newSpacing.height;
  509. getColumnModel().setColumnMargin(newSpacing.width);
  510. resizeAndRepaint();
  511. }
  512. /**
  513. * Returns the horizontal and vertical spacing between cells.
  514. * The default spacing is (3, 2).
  515. *
  516. * @return the horizontal and vertical spacing between cells
  517. * @see #setIntercellSpacing
  518. */
  519. public Dimension getIntercellSpacing() {
  520. return new Dimension(getColumnModel().getColumnMargin(), rowMargin);
  521. }
  522. /**
  523. * Sets the color used to draw grid lines to <I>color</I> and redisplays
  524. * the receiver. The default color is gray.
  525. *
  526. * @param color new color of the grid
  527. * @exception IllegalArgumentException if <I>color</I> is null
  528. * @see #getGridColor
  529. */
  530. public void setGridColor(Color newColor) {
  531. if (newColor == null) {
  532. throw new IllegalArgumentException("New color is null");
  533. }
  534. gridColor = newColor;
  535. // Redraw
  536. repaint();
  537. }
  538. /**
  539. * Returns the color used to draw grid lines. The default color is gray.
  540. *
  541. * @return the color used to draw grid lines
  542. * @see #setGridColor
  543. */
  544. public Color getGridColor() {
  545. return gridColor;
  546. }
  547. /**
  548. * Sets whether the receiver draws grid lines around cells.
  549. * If <I>flag</I> is true it does; if it is false it doesn't.
  550. * There is no getShowGrid() method as the this state is held
  551. * in two variables: showHorizontalLines and showVerticalLines
  552. * each of which may be queried independently.
  553. *
  554. * @param flag true if table view should draw grid lines
  555. *
  556. * @see #setShowVerticalLines
  557. * @see #setShowHorizontalLines
  558. * @beaninfo
  559. * description: The color used to draw the grid lines.
  560. */
  561. public void setShowGrid(boolean b) {
  562. setShowHorizontalLines(b);
  563. setShowVerticalLines(b);
  564. // Redraw
  565. repaint();
  566. }
  567. /**
  568. * Sets whether the receiver draws horizontal lines between cells.
  569. * If <I>flag</I> is true it does; if it is false it doesn't.
  570. *
  571. * @param flag true if table view should draw horizontal lines
  572. * @see #getShowHorizontalLines
  573. * @see #setShowGrid
  574. * @see #setShowVerticalLines
  575. * @beaninfo
  576. * description: Whether horizontal lines should be drawn in between the cells.
  577. */
  578. public void setShowHorizontalLines(boolean b) {
  579. showHorizontalLines = b;
  580. // Redraw
  581. repaint();
  582. }
  583. /**
  584. * Sets whether the receiver draws vertical lines between cells.
  585. * If <I>flag</I> is true it does; if it is false it doesn't.
  586. *
  587. * @param flag true if table view should draw vertical lines
  588. * @see #getShowVerticalLines
  589. * @see #setShowGrid
  590. * @see #setShowHorizontalLines
  591. * @beaninfo
  592. * description: Whether vertical lines should be drawn in between the cells.
  593. */
  594. public void setShowVerticalLines(boolean b) {
  595. showVerticalLines = b;
  596. // Redraw
  597. repaint();
  598. }
  599. /**
  600. * Returns true if the receiver draws horizontal lines between cells, false if it
  601. * doesn't. The default is true.
  602. *
  603. * @return true if the receiver draws horizontal lines between cells, false if it
  604. * doesn't
  605. * @see #setShowHorizontalLines
  606. */
  607. public boolean getShowHorizontalLines() {
  608. return showHorizontalLines;
  609. }
  610. /**
  611. * Returns true if the receiver draws vertical lines between cells, false if it
  612. * doesn't. The default is true.
  613. *
  614. * @return true if the receiver draws vertical lines between cells, false if it
  615. * doesn't
  616. * @see #setShowVerticalLines
  617. */
  618. public boolean getShowVerticalLines() {
  619. return showVerticalLines;
  620. }
  621. /**
  622. * Sets the table's auto resize mode when the table is resized.
  623. *
  624. * @param mode One of 5 legal values:
  625. * AUTO_RESIZE_OFF,
  626. * AUTO_RESIZE_NEXT_COLUMN,
  627. * AUTO_RESIZE_SUBSEQUENT_COLUMNS,
  628. * AUTO_RESIZE_LAST_COLUMN,
  629. * AUTO_RESIZE_ALL_COLUMNS
  630. *
  631. * @see #getAutoResizeMode
  632. * @see #sizeColumnsToFit(int)
  633. * @beaninfo
  634. * description: Whether the columns should adjust themselves automatically.
  635. * enum: AUTO_RESIZE_OFF JTable.AUTO_RESIZE_OFF
  636. * AUTO_RESIZE_NEXT_COLUMN JTable.AUTO_RESIZE_NEXT_COLUMN
  637. * AUTO_RESIZE_SUBSEQUENT_COLUMNS JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS
  638. * AUTO_RESIZE_LAST_COLUMN JTable.AUTO_RESIZE_LAST_COLUMN
  639. * AUTO_RESIZE_ALL_COLUMNS JTable.AUTO_RESIZE_ALL_COLUMNS
  640. */
  641. public void setAutoResizeMode(int mode) {
  642. if ((mode == AUTO_RESIZE_OFF) ||
  643. (mode == AUTO_RESIZE_NEXT_COLUMN) ||
  644. (mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) ||
  645. (mode == AUTO_RESIZE_LAST_COLUMN) ||
  646. (mode == AUTO_RESIZE_ALL_COLUMNS)) {
  647. autoResizeMode = mode;
  648. resizeAndRepaint();
  649. if (tableHeader != null) {
  650. tableHeader.resizeAndRepaint();
  651. }
  652. }
  653. }
  654. /**
  655. * Returns auto resize mode of the table.
  656. *
  657. * @return the autoResizeMode of the table
  658. *
  659. * @see #setAutoResizeMode
  660. * @see #sizeColumnsToFit(int)
  661. */
  662. public int getAutoResizeMode() {
  663. return autoResizeMode;
  664. }
  665. /**
  666. * Sets the table's autoCreateColumnsFromModel flag. This method
  667. * will call createDefaultColumnsFromModel() if <i>createColumns</i>
  668. * is true.
  669. *
  670. * @param createColumns true if JTable should auto create columns
  671. * @see #getAutoCreateColumnsFromModel
  672. * @see #createDefaultColumnsFromModel
  673. * @beaninfo
  674. * description: Automatically populate the columnModel when a new TableModel is submitted.
  675. */
  676. public void setAutoCreateColumnsFromModel(boolean createColumns) {
  677. if (autoCreateColumnsFromModel != createColumns) {
  678. autoCreateColumnsFromModel = createColumns;
  679. if (autoCreateColumnsFromModel)
  680. createDefaultColumnsFromModel();
  681. }
  682. }
  683. /**
  684. * Returns whether the table will create default columns from the model.
  685. * If this is true, setModel() will clear any existing columns and
  686. * create new columns from the new model. Also if the event in the
  687. * the tableChanged() notification specified the entired table changed
  688. * then the columns will be rebuilt. The default is true.
  689. *
  690. * @return the autoCreateColumnsFromModel of the table
  691. * @see #setAutoCreateColumnsFromModel
  692. * @see #createDefaultColumnsFromModel
  693. */
  694. public boolean getAutoCreateColumnsFromModel() {
  695. return autoCreateColumnsFromModel;
  696. }
  697. /**
  698. * This method will create default columns for the table from
  699. * the data model using the getColumnCount() and getColumnClass() methods
  700. * defined in the TableModel interface.
  701. * <p>
  702. * This method will clear any exsiting columns before creating the
  703. * new columns based on information from the model.
  704. *
  705. * @see #getAutoCreateColumnsFromModel
  706. */
  707. public void createDefaultColumnsFromModel() {
  708. TableModel m = getModel();
  709. if (m != null) {
  710. // Remove any current columns
  711. TableColumnModel cm = getColumnModel();
  712. cm.removeColumnModelListener(this);
  713. while (cm.getColumnCount() > 0)
  714. cm.removeColumn(cm.getColumn(0));
  715. // Create new columns from the data model info
  716. for (int i = 0; i < m.getColumnCount(); i++) {
  717. TableColumn newColumn = new TableColumn(i);
  718. addColumn(newColumn);
  719. }
  720. cm.addColumnModelListener(this);
  721. }
  722. }
  723. /**
  724. * Set a default renderer to be used if no renderer has been set in
  725. * a TableColumn. If renderer is null, remove the default renderer
  726. * for this column class.
  727. *
  728. * @see #getDefaultRenderer
  729. * @see #setDefaultEditor
  730. */
  731. public void setDefaultRenderer(Class columnClass, TableCellRenderer renderer) {
  732. if (renderer != null) {
  733. defaultRenderersByColumnClass.put(columnClass, renderer);
  734. }
  735. else {
  736. defaultRenderersByColumnClass.remove(columnClass);
  737. }
  738. }
  739. /**
  740. * Returns the renderer to be used when no renderer has been set in
  741. * a TableColumn. During the rendering of cells the renderer is fetched from
  742. * a Hashtable of entries according to the class of the cells in the column. If
  743. * there is no entry for this <I>columnClass</I> the method returns
  744. * the entry for the most specific superclass. The JTable installs entries
  745. * for <I>Object</I>, <I>Number</I> and <I>Boolean</I> all which can be modified
  746. * or replaced.
  747. *
  748. * @see #setDefaultRenderer
  749. * @see #getColumnClass
  750. */
  751. public TableCellRenderer getDefaultRenderer(Class columnClass) {
  752. if (columnClass == null) {
  753. return null;
  754. }
  755. else {
  756. Object renderer = defaultRenderersByColumnClass.get(columnClass);
  757. if (renderer != null) {
  758. return (TableCellRenderer)renderer;
  759. }
  760. else {
  761. return getDefaultRenderer(columnClass.getSuperclass());
  762. }
  763. }
  764. }
  765. /**
  766. * Set a default editor to be used if no editor has been set in
  767. * a TableColumn. If no editing is required in a table, or a
  768. * particular column in a table, use the isCellEditable()
  769. * method in the TableModel interface to ensure that the
  770. * JTable will not start an editor in these columns.
  771. * If editor is null, remove the default editor for this
  772. * column class.
  773. *
  774. * @see TableModel#isCellEditable
  775. * @see #getDefaultEditor
  776. * @see #setDefaultRenderer
  777. */
  778. public void setDefaultEditor(Class columnClass, TableCellEditor editor) {
  779. if (editor != null) {
  780. defaultEditorsByColumnClass.put(columnClass, editor);
  781. }
  782. else {
  783. defaultEditorsByColumnClass.remove(columnClass);
  784. }
  785. }
  786. /**
  787. * Returns the editor to be used when no editor has been set in
  788. * a TableColumn. During the editing of cells the editor is fetched from
  789. * a Hashtable of entries according to the class of the cells in the column. If
  790. * there is no entry for this <I>columnClass</I> the method returns
  791. * the entry for the most specific superclass. The JTable installs entries
  792. * for <I>Object</I>, <I>Number</I> and <I>Boolean</I> all which can be modified
  793. * or replaced.
  794. *
  795. * @see #setDefaultEditor
  796. * @see #getColumnClass
  797. */
  798. public TableCellEditor getDefaultEditor(Class columnClass) {
  799. if (columnClass == null) {
  800. return null;
  801. }
  802. else {
  803. Object editor = defaultEditorsByColumnClass.get(columnClass);
  804. if (editor != null) {
  805. return (TableCellEditor)editor;
  806. }
  807. else {
  808. return getDefaultEditor(columnClass.getSuperclass());
  809. }
  810. }
  811. }
  812. //
  813. // Selection methods
  814. //
  815. /**
  816. * Sets the table's selection mode to allow only single selections, a single
  817. * contiguous interval, or multiple intervals.
  818. *
  819. * NOTE:<br>
  820. * JTable provides all the methods for handling column and row selection.
  821. * When setting states, such as setSelectionMode, it not only
  822. * updates the mode for the row selection model but also sets similar
  823. * values in the selection model of the columnModel.
  824. * If you want to have the row and column selection models operating
  825. * in different modes, set them both directly.
  826. * <p>
  827. * Both the row and column selection models for the JTable default
  828. * to using a DefaultListSelectionModel so that JTable works the same
  829. * way as the JList. See setSelectionMode() in JList for details
  830. * about the modes.
  831. *
  832. * @see JList#setSelectionMode
  833. * @beaninfo
  834. * description: The selection mode used by the row and column selection models.
  835. * enum: SINGLE_SELECTION ListSelectionModel.SINGLE_SELECTION
  836. * SINGLE_INTERVAL_SELECTION ListSelectionModel.SINGLE_INTERVAL_SELECTION
  837. * MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
  838. */
  839. public void setSelectionMode(int selectionMode) {
  840. clearSelection();
  841. getSelectionModel().setSelectionMode(selectionMode);
  842. getColumnModel().getSelectionModel().setSelectionMode(selectionMode);
  843. }
  844. /**
  845. * Sets whether the rows in this model can be selected.
  846. *
  847. * @see #getRowSelectionAllowed
  848. * @beaninfo
  849. * description: If true, an entire row is selected for each selected cell.
  850. */
  851. public void setRowSelectionAllowed(boolean flag) {
  852. rowSelectionAllowed = flag;
  853. }
  854. /**
  855. * Returns true if rows can be selected.
  856. *
  857. * @return true if rows can be selected
  858. * @see #setRowSelectionAllowed
  859. */
  860. public boolean getRowSelectionAllowed() {
  861. return rowSelectionAllowed;
  862. }
  863. /**
  864. * Sets whether the columns in this model can be selected.
  865. *
  866. * @see #getColumnSelectionAllowed
  867. * @beaninfo
  868. * description: If true, an entire column is selected for each selected cell.
  869. */
  870. public void setColumnSelectionAllowed(boolean flag) {
  871. columnModel.setColumnSelectionAllowed(flag);
  872. }
  873. /**
  874. * Returns true if columns can be selected.
  875. *
  876. * @return true if columns can be selected.
  877. * @see #setColumnSelectionAllowed
  878. */
  879. public boolean getColumnSelectionAllowed() {
  880. return columnModel.getColumnSelectionAllowed();
  881. }
  882. /**
  883. * Sets whether this table allows both a column selection and a
  884. * row selection to exist at the same time. When set, this results
  885. * in a facility to select a rectangular region of cells in the display.
  886. * This flag over-rides the row and column selection
  887. * modes ensuring that cell selection is possible whenever this flag is set.
  888. * @see #getCellSelectionEnabled
  889. * @beaninfo
  890. * description: Select a rectangular region of cells rather than rows or columns.
  891. */
  892. public void setCellSelectionEnabled(boolean flag) {
  893. cellSelectionEnabled = flag;
  894. }
  895. /**
  896. * Returns true if simultaneous row and column selections are allowed
  897. *
  898. * @return true if simultaneous row and column selections are allowed
  899. * @see #setCellSelectionEnabled
  900. */
  901. public boolean getCellSelectionEnabled() {
  902. return cellSelectionEnabled;
  903. }
  904. /**
  905. * Select all rows, columns and cells in the table.
  906. */
  907. public void selectAll() {
  908. // If I'm currently editing, then I should stop editing
  909. if (isEditing()) {
  910. removeEditor();
  911. }
  912. setRowSelectionInterval(0, getRowCount()-1);
  913. setColumnSelectionInterval(0, getColumnCount()-1);
  914. }
  915. /**
  916. * Deselects all selected columns and rows.
  917. */
  918. public void clearSelection() {
  919. columnModel.getSelectionModel().clearSelection();
  920. selectionModel.clearSelection();
  921. }
  922. /**
  923. * Selects the rows from <i>index0</i> to <i>index1</i> inclusive.
  924. *
  925. * @param index0 one end of the interval.
  926. * @param index1 other end of the interval
  927. */
  928. public void setRowSelectionInterval(int index0, int index1) {
  929. selectionModel.setSelectionInterval(index0, index1);
  930. }
  931. /**
  932. * Selects the columns from <i>index0</i> to <i>index1</i> inclusive.
  933. *
  934. * @param index0 one end of the interval.
  935. * @param index1 other end of the interval
  936. */
  937. public void setColumnSelectionInterval(int index0, int index1) {
  938. columnModel.getSelectionModel().setSelectionInterval(index0, index1);
  939. }
  940. /**
  941. * Adds the rows from <i>index0</i> to <i>index0</i> inclusive to
  942. * the current selection.
  943. *
  944. * @param index0 one end of the interval.
  945. * @param index1 other end of the interval
  946. */
  947. public void addRowSelectionInterval(int index0, int index1) {
  948. selectionModel.addSelectionInterval(index0, index1);
  949. }
  950. /**
  951. * Adds the columns from <i>index0</i> to <i>index0</i> inclusive to
  952. * the current selection.
  953. *
  954. * @param index0 one end of the interval.
  955. * @param index1 other end of the interval
  956. */
  957. public void addColumnSelectionInterval(int index0, int index1) {
  958. columnModel.getSelectionModel().addSelectionInterval(index0, index1);
  959. }
  960. /**
  961. * Deselects the rows from <i>index0</i> to <i>index0</i> inclusive.
  962. *
  963. * @param index0 one end of the interval.
  964. * @param index1 other end of the interval
  965. */
  966. public void removeRowSelectionInterval(int index0, int index1) {
  967. selectionModel.removeSelectionInterval(index0, index1);
  968. }
  969. /**
  970. * Deselects the columns from <i>index0</i> to <i>index0</i> inclusive.
  971. *
  972. * @param index0 one end of the interval.
  973. * @param index1 other end of the interval
  974. */
  975. public void removeColumnSelectionInterval(int index0, int index1) {
  976. columnModel.getSelectionModel().removeSelectionInterval(index0, index1);
  977. }
  978. /**
  979. * Returns the index of the first selected row, -1 if no row is selected.
  980. */
  981. public int getSelectedRow() {
  982. return selectionModel.getMinSelectionIndex();
  983. }
  984. /**
  985. * Returns the index of the first selected column, -1 if no column is selected.
  986. */
  987. public int getSelectedColumn() {
  988. return columnModel.getSelectionModel().getMinSelectionIndex();
  989. }
  990. /**
  991. * Returns the indices of all selected rows.
  992. *
  993. * @return an array of ints containing the indices of all selected rows,
  994. * or an empty array if no row is selected.
  995. * @see #getSelectedRow
  996. */
  997. public int[] getSelectedRows() {
  998. if (selectionModel != null) {
  999. int iMin = selectionModel.getMinSelectionIndex();
  1000. int iMax = selectionModel.getMaxSelectionIndex();
  1001. if ((iMin == -1) || (iMax == -1)) {
  1002. return new int[0];
  1003. }
  1004. int[] rvTmp = new int[1+ (iMax - iMin)];
  1005. int n = 0;
  1006. for(int i = iMin; i <= iMax; i++) {
  1007. if (selectionModel.isSelectedIndex(i)) {
  1008. rvTmp[n++] = i;
  1009. }
  1010. }
  1011. int[] rv = new int[n];
  1012. System.arraycopy(rvTmp, 0, rv, 0, n);
  1013. return rv;
  1014. }
  1015. return new int[0];
  1016. }
  1017. /**
  1018. * Returns the indices of all selected columns.
  1019. *
  1020. * @return an array of ints containing the indices of all selected columns,
  1021. * or an empty array if no column is selected.
  1022. * @see #getSelectedColumn
  1023. */
  1024. public int[] getSelectedColumns() {
  1025. return columnModel.getSelectedColumns();
  1026. }
  1027. /**
  1028. * Returns the number of selected rows.
  1029. *
  1030. * @return the number of selected rows, 0 if no columns are selected
  1031. */
  1032. public int getSelectedRowCount() {
  1033. if (selectionModel != null) {
  1034. int iMin = selectionModel.getMinSelectionIndex();
  1035. int iMax = selectionModel.getMaxSelectionIndex();
  1036. int count = 0;
  1037. for(int i = iMin; i <= iMax; i++) {
  1038. if (selectionModel.isSelectedIndex(i)) {
  1039. count++;
  1040. }
  1041. }
  1042. return count;
  1043. }
  1044. return 0;
  1045. }
  1046. /**
  1047. * Returns the number of selected columns.
  1048. *
  1049. * @return the number of selected columns, 0 if no columns are selected
  1050. */
  1051. public int getSelectedColumnCount() {
  1052. return columnModel.getSelectedColumnCount();
  1053. }
  1054. /**
  1055. * Returns true if the row at the specified index is selected
  1056. *
  1057. * @return true if the row at index <I>row</I> is selected, where 0 is the
  1058. * first row
  1059. * @exception IllegalArgumentException if <I>row</I> is not in the
  1060. * valid range
  1061. */
  1062. public boolean isRowSelected(int row) {
  1063. if (selectionModel != null)
  1064. return selectionModel.isSelectedIndex(row);
  1065. return false;
  1066. }
  1067. /**
  1068. * Returns true if the column at the specified index is selected
  1069. *
  1070. * @return true if the column at index <I>column</I> is selected, where
  1071. * 0 is the first column
  1072. * @exception IllegalArgumentException if <I>column</I> is not in the
  1073. * valid range
  1074. */
  1075. public boolean isColumnSelected(int column) {
  1076. return columnModel.getSelectionModel().isSelectedIndex(column);
  1077. }
  1078. /**
  1079. * Returns true if the cell at the specified position is selected.
  1080. *
  1081. * @return true if the cell at index <I>(row, column)</I> is selected,
  1082. * where the first row and first column are at index 0
  1083. * @exception IllegalArgumentException if <I>row</I> or <I>column</I>
  1084. * are not in the valid range
  1085. */
  1086. public boolean isCellSelected(int row, int column) {
  1087. if (cellSelectionEnabled)
  1088. return isRowSelected(row) && isColumnSelected(column);
  1089. else
  1090. return (getRowSelectionAllowed() && isRowSelected(row)) ||
  1091. (getColumnSelectionAllowed() && isColumnSelected(column));
  1092. }
  1093. /**
  1094. * Returns the foreground color for selected cells.
  1095. *
  1096. * @return the Color object for the foreground property
  1097. * @see #setSelectionForeground
  1098. * @see #setSelectionBackground
  1099. */
  1100. public Color getSelectionForeground() {
  1101. return selectionForeground;
  1102. }
  1103. /**
  1104. * Set the foreground color for selected cells. Cell renderers
  1105. * can use this color to render text and graphics for selected
  1106. * cells.
  1107. * <p>
  1108. * The default value of this property is defined by the look
  1109. * and feel implementation.
  1110. * <p>
  1111. * This is a JavaBeans bound property.
  1112. *
  1113. * @param selectionForeground the Color to use in the foreground
  1114. * for selected list items
  1115. * @see #getSelectionForeground
  1116. * @see #setSelectionBackground
  1117. * @see #setForeground
  1118. * @see #setBackground
  1119. * @see #setFont
  1120. * @beaninfo
  1121. * bound: true
  1122. * description: A default foreground color for selected cells.
  1123. */
  1124. public void setSelectionForeground(Color selectionForeground) {
  1125. Color oldValue = this.selectionForeground;
  1126. this.selectionForeground = selectionForeground;
  1127. firePropertyChange("selectionForeground", oldValue, selectionForeground);
  1128. }
  1129. /**
  1130. * Returns the background color for selected cells.
  1131. *
  1132. * @return the Color used for the background of selected list items
  1133. * @see #setSelectionBackground
  1134. * @see #setSelectionForeground
  1135. */
  1136. public Color getSelectionBackground() {
  1137. return selectionBackground;
  1138. }
  1139. /**
  1140. * Set the background color for selected cells. Cell renderers
  1141. * can use this color to the fill selected cells.
  1142. * <p>
  1143. * The default value of this property is defined by the look
  1144. * and feel implementation.
  1145. * <p>
  1146. * This is a JavaBeans bound property.
  1147. *
  1148. * @param selectionBackground the Color to use for the background
  1149. * of selected cells
  1150. * @see #getSelectionBackground
  1151. * @see #setSelectionForeground
  1152. * @see #setForeground
  1153. * @see #setBackground
  1154. * @see #setFont
  1155. * @beaninfo
  1156. * bound: true
  1157. * description: A default background color for selected cells.
  1158. */
  1159. public void setSelectionBackground(Color selectionBackground) {
  1160. Color oldValue = this.selectionBackground;
  1161. this.selectionBackground = selectionBackground;
  1162. firePropertyChange("selectionBackground", oldValue, selectionBackground);
  1163. }
  1164. /**
  1165. * Returns the <B>TableColumn</B> object for the column in the table
  1166. * whose identifier is equal to <I>identifier</I>, when compared using
  1167. * <I>equals()</I>.
  1168. *
  1169. * @return the TableColumn object with matching identifier
  1170. * @exception IllegalArgumentException if <I>identifier</I> is null or no TableColumn has this identifier
  1171. *
  1172. * @param identifier the identifier object
  1173. */
  1174. public TableColumn getColumn(Object identifier) {
  1175. TableColumnModel cm = getColumnModel();
  1176. int columnIndex = cm.getColumnIndex(identifier);
  1177. return cm.getColumn(columnIndex);
  1178. }
  1179. //
  1180. // Informally implement the TableModel interface.
  1181. //
  1182. /**
  1183. * Return the index of the column in the model whose data is being displayed in
  1184. * the column <I>viewColumnIndex</I> in the display. Returns <I>viewColumnIndex</I>
  1185. * unchanged when <I>viewColumnIndex</I> is less than zero.
  1186. *
  1187. * @see #convertColumnIndexToView
  1188. */
  1189. public int convertColumnIndexToModel(int viewColumnIndex) {
  1190. if (viewColumnIndex < 0) {
  1191. return viewColumnIndex;
  1192. }
  1193. return getColumnModel().getColumn(viewColumnIndex).getModelIndex();
  1194. }
  1195. /**
  1196. * Return the index of the column in the view which is displaying the
  1197. * data from the column <I>modelColumnIndex</I> in the model. Returns
  1198. * -1 if this column is not being displayed. Returns <I>modelColumnIndex</I>
  1199. * unchanged when <I>modelColumnIndex</I> is less than zero.
  1200. *
  1201. * @see #convertColumnIndexToModel
  1202. */
  1203. public int convertColumnIndexToView(int modelColumnIndex) {
  1204. if (modelColumnIndex < 0) {
  1205. return modelColumnIndex;
  1206. }
  1207. TableColumnModel cm = getColumnModel();
  1208. for (int column = 0; column < getColumnCount(); column++) {
  1209. if (cm.getColumn(column).getModelIndex() == modelColumnIndex) {
  1210. return column;
  1211. }
  1212. }
  1213. return -1;
  1214. }
  1215. /**
  1216. * Returns the number of rows in the table.
  1217. *
  1218. * @see #getColumnCount
  1219. */
  1220. public int getRowCount() {
  1221. return getModel().getRowCount();
  1222. }
  1223. /**
  1224. * Returns the number of columns in the column model, note this may
  1225. * be different to the number of columns in the table model.
  1226. *
  1227. * @return the number of columns in the table
  1228. * @see #getRowCount
  1229. */
  1230. public int getColumnCount() {
  1231. return getColumnModel().getColumnCount();
  1232. }
  1233. /**
  1234. * Returns the name of the column at the specified view position.
  1235. *
  1236. * @return the name of the column at position <I>column</I> in the view
  1237. * where the first column is column 0.
  1238. */
  1239. public String getColumnName(int column) {
  1240. return getModel().getColumnName(convertColumnIndexToModel(column));
  1241. }
  1242. /**
  1243. * Returns the type of the column at the specified view position.
  1244. *
  1245. * @return the type of the column at position <I>column</I> in the view
  1246. * where the first column is column 0.
  1247. */
  1248. public Class getColumnClass(int column) {
  1249. return getModel().getColumnClass(convertColumnIndexToModel(column));
  1250. }
  1251. /**
  1252. * Returns the cell value at <I>row</I> and <I>column</I>.
  1253. * <p>
  1254. * <b>NOTE</b>: The column is specified in the table view's display
  1255. * order, and not in the TableModel's column order. This is
  1256. * an important distinction because as the user rearranges
  1257. * the columns in the table, what is at column 2 changes.
  1258. * Meanwhile the user's actions never affect the model's
  1259. * column ordering.
  1260. *
  1261. * @param row the row whose value is to be looked up
  1262. * @param column the column whose value is to be looked up
  1263. * @return the Object at the specified cell
  1264. */
  1265. public Object getValueAt(int row, int column) {
  1266. return getModel().getValueAt(row, convertColumnIndexToModel(column));
  1267. }
  1268. /**
  1269. * Sets the value for the cell at <I>row</I> and <I>column</I>.
  1270. * <I>aValue</I> is the new value.
  1271. *
  1272. * @param aValue the new value
  1273. * @param row the row whose value is to be changed
  1274. * @param column the column whose value is to be changed
  1275. * @see #getValueAt
  1276. */
  1277. public void setValueAt(Object aValue, int row, int column) {
  1278. getModel().setValueAt(aValue, row, convertColumnIndexToModel(column));
  1279. }
  1280. /**
  1281. * Returns true if the cell at <I>row</I> and <I>column</I>
  1282. * is editable. Otherwise, setValueAt() on the cell will not change
  1283. * the value of that cell.
  1284. *
  1285. * @param row the row whose value is to be looked up
  1286. * @param column the column whose value is to be looked up
  1287. * @return true if the cell is editable.
  1288. * @see #setValueAt
  1289. */
  1290. public boolean isCellEditable(int row, int column) {
  1291. return getModel().isCellEditable(row, convertColumnIndexToModel(column));
  1292. }
  1293. //
  1294. // Adding and removing columns in the view
  1295. //
  1296. /**
  1297. * Appends <I>aColumn</I> to the end of the array of columns held by
  1298. * the JTable's column model.
  1299. * If the header value of <I>aColumn</I> is <I>null</I>,
  1300. * sets the header value of <I>aColumn</I> to the name
  1301. * returned by <code>getModel().getColumnName()</code>.
  1302. * <p>
  1303. * To add a column to the JTable to display the <I>modelColumn</I>'th column of
  1304. * data in the model, with a given <I>width</I>,
  1305. * <I>cellRenderer</I> and <I>cellEditor</I> you can use:
  1306. * <pre>
  1307. *
  1308. * addColumn(new TableColumn(modelColumn, width, cellRenderer, cellEditor));
  1309. *
  1310. * </pre>
  1311. * [All of the other constructors in the TableColumn can be used in place of
  1312. * this one.] The model column is stored inside the TableColumn and is used during
  1313. * rendering and editing to locate the appropriate data values in the
  1314. * model. The model column does not change when columns are reordered
  1315. * in the view.
  1316. *
  1317. * @param aColumn The <B>TableColumn</B> to be added
  1318. * @see #removeColumn
  1319. */
  1320. public void addColumn(TableColumn aColumn) {
  1321. int modelColumn = aColumn.getModelIndex();
  1322. String columnName = getModel().getColumnName(modelColumn);
  1323. if (aColumn.getHeaderValue() == null) {
  1324. aColumn.setHeaderValue(columnName);
  1325. }
  1326. getColumnModel().addColumn(aColumn);
  1327. }
  1328. /**
  1329. * Removes <I>aColumn</I> from the JTable's array of columns.
  1330. * Note: this method does not remove the column of data from the
  1331. * model it just removes the TableColumn that was displaying it.
  1332. *
  1333. * @param aColumn The <B>TableColumn</B> to be removed
  1334. * @see #addColumn
  1335. */
  1336. public void removeColumn(TableColumn aColumn) {
  1337. getColumnModel().removeColumn(aColumn);
  1338. }
  1339. /**
  1340. * Moves the column <I>column</I> to the position currently occupied by the
  1341. * column <I>targetColumn</I>. The old column at <I>targetColumn</I> is
  1342. * shifted left or right to make room.
  1343. *
  1344. * @param column the index of column to be moved
  1345. * @param targetColumn the new index of the column
  1346. */
  1347. public void moveColumn(int column, int targetColumn) {
  1348. getColumnModel().moveColumn(column, targetColumn);
  1349. }
  1350. //
  1351. // Cover methods for various models and helper methods
  1352. //
  1353. /**
  1354. * Returns the index of the column that <I>point</I> lies in, or -1 if it
  1355. * lies outside the receiver's bounds.
  1356. *
  1357. * @return the index of the column that <I>point</I> lies in, or -1 if it
  1358. * lies outside the receiver's bounds
  1359. * @see #rowAtPoint
  1360. */
  1361. public int columnAtPoint(Point point) {
  1362. return getColumnModel().getColumnIndexAtX(point.x);
  1363. }
  1364. /**
  1365. * Returns the index of the row that <I>point</I> lies in, or -1 if is
  1366. * not in the range [0, getRowCount()-1].
  1367. *
  1368. * @return the index of the row that <I>point</I> lies in, or -1 if it
  1369. * is not in the range [0, getRowCount()-1]
  1370. * @see #columnAtPoint
  1371. */
  1372. public int rowAtPoint(Point point) {
  1373. int y = point.y;
  1374. // if (y < 0 || y >= getBounds().height) {
  1375. // return -1;
  1376. // }
  1377. int rowHeight = getRowHeight();
  1378. int rowSpacing = getIntercellSpacing().height;
  1379. int totalRowHeight = rowHeight + rowSpacing;
  1380. int result = ytotalRowHeight;
  1381. if (result < 0) {
  1382. return -1;
  1383. }
  1384. else if (result >= getRowCount()) {
  1385. return -1;
  1386. }
  1387. else {
  1388. return result;
  1389. }
  1390. }
  1391. /**
  1392. * Returns a rectangle locating the cell that lies at the intersection of
  1393. * <I>row</I> and <I>column</I>. If <I>includeSpacing</I> is true then
  1394. * the value returned includes the intercellSpacing margin. If it is false,
  1395. * then the returned rect is inset by half of intercellSpacing.
  1396. * (This is the true frame of the cell)
  1397. *
  1398. * @param row the row to compute
  1399. * @param column the column to compute
  1400. * @param includeSpacing if true, the rect returned will
  1401. * include the correct
  1402. * intercellSpacing
  1403. * @return the rectangle containing the cell at index
  1404. * <I>row</I>,<I>column</I>
  1405. * @exception IllegalArgumentException If <I>row</I> or <I>column</I>
  1406. * are not in the valid range.
  1407. */
  1408. public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
  1409. int index = 0;
  1410. Rectangle cellFrame;
  1411. int columnMargin = getColumnModel().getColumnMargin();
  1412. Enumeration enumeration = getColumnModel().getColumns();
  1413. TableColumn aColumn;
  1414. cellFrame = new Rectangle();
  1415. cellFrame.height = getRowHeight() + rowMargin;
  1416. cellFrame.y = row * cellFrame.height;
  1417. while (enumeration.hasMoreElements()) {
  1418. aColumn = (TableColumn)enumeration.nextElement();
  1419. cellFrame.width = aColumn.getWidth() + columnMargin;
  1420. if (index == column)
  1421. break;
  1422. cellFrame.x += cellFrame.width;
  1423. index++;
  1424. }
  1425. if (!includeSpacing) {
  1426. Dimension spacing = getIntercellSpacing();
  1427. // This is not the same as grow(), it rounds differently.
  1428. cellFrame.setBounds(cellFrame.x + spacing.width2,
  1429. cellFrame.y + spacing.height2,
  1430. cellFrame.width - spacing.width,
  1431. cellFrame.height - spacing.height);
  1432. }
  1433. return cellFrame;
  1434. }
  1435. /**
  1436. * Calls super.reshape(), and is overridden simply to detect changes in
  1437. * our bounds. After reshaping we resize the columns (similar to triggering
  1438. * a layout) to fit the new bounds for the component using sizeColumnsToFit().
  1439. *
  1440. * @see #sizeColumnsToFit(int)
  1441. */
  1442. public void reshape(int x, int y, int width, int height) {