KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > JTable


1 /*
2  * @(#)JTable.java 1.240 06/03/28
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.swing;
9
10 import java.util.*;
11
12 import java.applet.Applet JavaDoc;
13 import java.awt.*;
14 import java.awt.event.*;
15 import java.awt.print.*;
16
17 import java.beans.*;
18
19 import java.io.Serializable JavaDoc;
20 import java.io.ObjectOutputStream JavaDoc;
21 import java.io.ObjectInputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23
24 import javax.accessibility.*;
25
26 import javax.swing.event.*;
27 import javax.swing.plaf.*;
28 import javax.swing.table.*;
29 import javax.swing.border.*;
30
31 import java.text.NumberFormat JavaDoc;
32 import java.text.DateFormat JavaDoc;
33 import java.text.MessageFormat JavaDoc;
34
35 import javax.print.attribute.*;
36
37 /**
38  * The <code>JTable</code> is used to display and edit regular two-dimensional tables
39  * of cells.
40  * See <a HREF="http://java.sun.com/docs/books/tutorial/uiswing/components/table.html">How to Use Tables</a>
41  * in <em>The Java Tutorial</em>
42  * for task-oriented documentation and examples of using <code>JTable</code>.
43  *
44  * <p>
45  * The <code>JTable</code> has many
46  * facilities that make it possible to customize its rendering and editing
47  * but provides defaults for these features so that simple tables can be
48  * set up easily. For example, to set up a table with 10 rows and 10
49  * columns of numbers:
50  * <p>
51  * <pre>
52  * TableModel dataModel = new AbstractTableModel() {
53  * public int getColumnCount() { return 10; }
54  * public int getRowCount() { return 10;}
55  * public Object getValueAt(int row, int col) { return new Integer(row*col); }
56  * };
57  * JTable table = new JTable(dataModel);
58  * JScrollPane scrollpane = new JScrollPane(table);
59  * </pre>
60  * <p>
61  * Note that if you wish to use a <code>JTable</code> in a standalone
62  * view (outside of a <code>JScrollPane</code>) and want the header
63  * displayed, you can get it using {@link #getTableHeader} and
64  * display it separately.
65  * <p>
66  * When designing applications that use the <code>JTable</code> it is worth paying
67  * close attention to the data structures that will represent the table's data.
68  * The <code>DefaultTableModel</code> is a model implementation that
69  * uses a <code>Vector</code> of <code>Vector</code>s of <code>Object</code>s to
70  * store the cell values. As well as copying the data from an
71  * application into the <code>DefaultTableModel</code>,
72  * it is also possible to wrap the data in the methods of the
73  * <code>TableModel</code> interface so that the data can be passed to the
74  * <code>JTable</code> directly, as in the example above. This often results
75  * in more efficient applications because the model is free to choose the
76  * internal representation that best suits the data.
77  * A good rule of thumb for deciding whether to use the <code>AbstractTableModel</code>
78  * or the <code>DefaultTableModel</code> is to use the <code>AbstractTableModel</code>
79  * as the base class for creating subclasses and the <code>DefaultTableModel</code>
80  * when subclassing is not required.
81  * <p>
82  * The "TableExample" directory in the demo area of the source distribution
83  * gives a number of complete examples of <code>JTable</code> usage,
84  * covering how the <code>JTable</code> can be used to provide an
85  * editable view of data taken from a database and how to modify
86  * the columns in the display to use specialized renderers and editors.
87  * <p>
88  * The <code>JTable</code> uses integers exclusively to refer to both the rows and the columns
89  * of the model that it displays. The <code>JTable</code> simply takes a tabular range of cells
90  * and uses <code>getValueAt(int, int)</code> to retrieve the
91  * values from the model during painting.
92  * <p>
93  * By default, columns may be rearranged in the <code>JTable</code> so that the
94  * view's columns appear in a different order to the columns in the model.
95  * This does not affect the implementation of the model at all: when the
96  * columns are reordered, the <code>JTable</code> maintains the new order of the columns
97  * internally and converts its column indices before querying the model.
98  * <p>
99  * So, when writing a <code>TableModel</code>, it is not necessary to listen for column
100  * reordering events as the model will be queried in its own coordinate
101  * system regardless of what is happening in the view.
102  * In the examples area there is a demonstration of a sorting algorithm making
103  * use of exactly this technique to interpose yet another coordinate system
104  * where the order of the rows is changed, rather than the order of the columns.
105  * <p>
106  * J2SE 5 adds methods to <code>JTable</code> to provide convenient access to some
107  * common printing needs. Simple new {@link #print()} methods allow for quick
108  * and easy addition of printing support to your application. In addition, a new
109  * {@link #getPrintable} method is available for more advanced printing needs.
110  * <p>
111  * As for all <code>JComponent</code> classes, you can use
112  * {@link InputMap} and {@link ActionMap} to associate an
113  * {@link Action} object with a {@link KeyStroke} and execute the
114  * action under specified conditions.
115  * <p>
116  * <strong>Warning:</strong>
117  * Serialized objects of this class will not be compatible with
118  * future Swing releases. The current serialization support is
119  * appropriate for short term storage or RMI between applications running
120  * the same version of Swing. As of 1.4, support for long term storage
121  * of all JavaBeans<sup><font size="-2">TM</font></sup>
122  * has been added to the <code>java.beans</code> package.
123  * Please see {@link java.beans.XMLEncoder}.
124  *
125  *
126  * @beaninfo
127  * attribute: isContainer false
128  * description: A component which displays data in a two dimensional grid.
129  *
130  * @version 1.240 03/28/06
131  * @author Philip Milne
132  * @author Shannon Hickey (printing support)
133  */

134 /* The first versions of the JTable, contained in Swing-0.1 through
135  * Swing-0.4, were written by Alan Chung.
136  */

137 public class JTable extends JComponent JavaDoc implements TableModelListener, Scrollable JavaDoc,
138     TableColumnModelListener, ListSelectionListener, CellEditorListener,
139     Accessible
140 {
141 //
142
// Static Constants
143
//
144

145     /**
146      * @see #getUIClassID
147      * @see #readObject
148      */

149     private static final String JavaDoc uiClassID = "TableUI";
150
151     /** Do not adjust column widths automatically; use a scrollbar. */
152     public static final int AUTO_RESIZE_OFF = 0;
153
154     /** When a column is adjusted in the UI, adjust the next column the opposite way. */
155     public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
156
157     /** During UI adjustment, change subsequent columns to preserve the total width;
158       * this is the default behavior. */

159     public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
160
161     /** During all resize operations, apply adjustments to the last column only. */
162     public static final int AUTO_RESIZE_LAST_COLUMN = 3;
163
164     /** During all resize operations, proportionately resize all columns. */
165     public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
166
167
168     /**
169      * Printing modes, used in printing <code>JTable</code>s.
170      *
171      * @see #print(JTable.PrintMode, MessageFormat, MessageFormat,
172      * boolean, PrintRequestAttributeSet, boolean)
173      * @see #getPrintable
174      * @since 1.5
175      */

176     public enum PrintMode {
177
178         /**
179          * Printing mode that prints the table at its current size,
180          * spreading both columns and rows across multiple pages if necessary.
181          */

182         NORMAL,
183         
184         /**
185          * Printing mode that scales the output smaller, if necessary,
186          * to fit the table's entire width (and thereby all columns) on each page;
187          * Rows are spread across multiple pages as necessary.
188          */

189         FIT_WIDTH
190     }
191
192
193 //
194
// Instance Variables
195
//
196

197     /** The <code>TableModel</code> of the table. */
198     protected TableModel dataModel;
199
200     /** The <code>TableColumnModel</code> of the table. */
201     protected TableColumnModel columnModel;
202
203     /** The <code>ListSelectionModel</code> of the table, used to keep track of row selections. */
204     protected ListSelectionModel JavaDoc selectionModel;
205
206     /** The <code>TableHeader</code> working with the table. */
207     protected JTableHeader tableHeader;
208
209     /** The height in pixels of each row in the table. */
210     protected int rowHeight;
211
212     /** The height in pixels of the margin between the cells in each row. */
213     protected int rowMargin;
214
215     /** The color of the grid. */
216     protected Color gridColor;
217
218     /** The table draws horizontal lines between cells if <code>showHorizontalLines</code> is true. */
219     protected boolean showHorizontalLines;
220
221     /** The table draws vertical lines between cells if <code>showVerticalLines</code> is true. */
222     protected boolean showVerticalLines;
223
224     /**
225      * Determines if the table automatically resizes the
226      * width of the table's columns to take up the entire width of the
227      * table, and how it does the resizing.
228      */

229     protected int autoResizeMode;
230
231     /**
232      * The table will query the <code>TableModel</code> to build the default
233      * set of columns if this is true.
234      */

235     protected boolean autoCreateColumnsFromModel;
236
237     /** Used by the <code>Scrollable</code> interface to determine the initial visible area. */
238     protected Dimension preferredViewportSize;
239
240     /** True if row selection is allowed in this table. */
241     protected boolean rowSelectionAllowed;
242
243     /**
244      * Obsolete as of Java 2 platform v1.3. Please use the
245      * <code>rowSelectionAllowed</code> property and the
246      * <code>columnSelectionAllowed</code> property of the
247      * <code>columnModel</code> instead. Or use the
248      * method <code>getCellSelectionEnabled</code>.
249      */

250     /*
251      * If true, both a row selection and a column selection
252      * can be non-empty at the same time, the selected cells are the
253      * the cells whose row and column are both selected.
254      */

255     protected boolean cellSelectionEnabled;
256
257     /** If editing, the <code>Component</code> that is handling the editing. */
258     transient protected Component editorComp;
259
260     /**
261      * The active cell editor object, that overwrites the screen real estate
262      * occupied by the current cell and allows the user to change its contents.
263      * {@code null} if the table isn't currently editing.
264      */

265     transient protected TableCellEditor cellEditor;
266
267     /** Identifies the column of the cell being edited. */
268     transient protected int editingColumn;
269
270     /** Identifies the row of the cell being edited. */
271     transient protected int editingRow;
272
273     /**
274      * A table of objects that display the contents of a cell,
275      * indexed by class as declared in <code>getColumnClass</code>
276      * in the <code>TableModel</code> interface.
277      */

278     transient protected Hashtable defaultRenderersByColumnClass;
279
280     /**
281      * A table of objects that display and edit the contents of a cell,
282      * indexed by class as declared in <code>getColumnClass</code>
283      * in the <code>TableModel</code> interface.
284      */

285     transient protected Hashtable defaultEditorsByColumnClass;
286
287     /** The foreground color of selected cells. */
288     protected Color selectionForeground;
289
290     /** The background color of selected cells. */
291     protected Color selectionBackground;
292
293 //
294
// Private state
295
//
296

297     private SizeSequence JavaDoc rowModel;
298     private boolean dragEnabled;
299     private boolean surrendersFocusOnKeystroke;
300     private PropertyChangeListener editorRemover = null;
301     /**
302      * The last value of getValueIsAdjusting from the column selection models
303      * columnSelectionChanged notification. Used to test if a repaint is
304      * needed.
305      */

306     private boolean columnSelectionAdjusting;
307     /**
308      * The last value of getValueIsAdjusting from the row selection models
309      * valueChanged notification. Used to test if a repaint is needed.
310      */

311     private boolean rowSelectionAdjusting;
312
313     /**
314      * A flag to indicate whether or not the table is currently being printed.
315      * Used by print() and prepareRenderer() to disable indication of the
316      * selection and focused cell while printing.
317      */

318     private boolean isPrinting = false;
319
320     /**
321      * To communicate errors between threads during printing.
322      */

323     private Throwable JavaDoc printError;
324
325     /**
326      * True when setRowHeight(int) has been invoked.
327      */

328     private boolean isRowHeightSet;
329
330 //
331
// Constructors
332
//
333

334     /**
335      * Constructs a default <code>JTable</code> that is initialized with a default
336      * data model, a default column model, and a default selection
337      * model.
338      *
339      * @see #createDefaultDataModel
340      * @see #createDefaultColumnModel
341      * @see #createDefaultSelectionModel
342      */

343     public JTable() {
344         this(null, null, null);
345     }
346
347     /**
348      * Constructs a <code>JTable</code> that is initialized with
349      * <code>dm</code> as the data model, a default column model,
350      * and a default selection model.
351      *
352      * @param dm the data model for the table
353      * @see #createDefaultColumnModel
354      * @see #createDefaultSelectionModel
355      */

356     public JTable(TableModel dm) {
357         this(dm, null, null);
358     }
359
360     /**
361      * Constructs a <code>JTable</code> that is initialized with
362      * <code>dm</code> as the data model, <code>cm</code>
363      * as the column model, and a default selection model.
364      *
365      * @param dm the data model for the table
366      * @param cm the column model for the table
367      * @see #createDefaultSelectionModel
368      */

369     public JTable(TableModel dm, TableColumnModel cm) {
370         this(dm, cm, null);
371     }
372
373     /**
374      * Constructs a <code>JTable</code> that is initialized with
375      * <code>dm</code> as the data model, <code>cm</code> as the
376      * column model, and <code>sm</code> as the selection model.
377      * If any of the parameters are <code>null</code> this method
378      * will initialize the table with the corresponding default model.
379      * The <code>autoCreateColumnsFromModel</code> flag is set to false
380      * if <code>cm</code> is non-null, otherwise it is set to true
381      * and the column model is populated with suitable
382      * <code>TableColumns</code> for the columns in <code>dm</code>.
383      *
384      * @param dm the data model for the table
385      * @param cm the column model for the table
386      * @param sm the row selection model for the table
387      * @see #createDefaultDataModel
388      * @see #createDefaultColumnModel
389      * @see #createDefaultSelectionModel
390      */

391     public JTable(TableModel dm, TableColumnModel cm, ListSelectionModel JavaDoc sm) {
392         super();
393         setLayout(null);
394
395     setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
396                JComponent.getManagingFocusForwardTraversalKeys());
397     setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
398                JComponent.getManagingFocusBackwardTraversalKeys());
399
400         if (cm == null) {
401             cm = createDefaultColumnModel();
402             autoCreateColumnsFromModel = true;
403         }
404         setColumnModel(cm);
405
406         if (sm == null) {
407             sm = createDefaultSelectionModel();
408         }
409     setSelectionModel(sm);
410
411     // Set the model last, that way if the autoCreatColumnsFromModel has
412
// been set above, we will automatically populate an empty columnModel
413
// with suitable columns for the new model.
414
if (dm == null) {
415             dm = createDefaultDataModel();
416         }
417     setModel(dm);
418
419         initializeLocalVars();
420         updateUI();
421     }
422
423     /**
424      * Constructs a <code>JTable</code> with <code>numRows</code>
425      * and <code>numColumns</code> of empty cells using
426      * <code>DefaultTableModel</code>. The columns will have
427      * names of the form "A", "B", "C", etc.
428      *
429      * @param numRows the number of rows the table holds
430      * @param numColumns the number of columns the table holds
431      * @see javax.swing.table.DefaultTableModel
432      */

433     public JTable(int numRows, int numColumns) {
434         this(new DefaultTableModel(numRows, numColumns));
435     }
436
437     /**
438      * Constructs a <code>JTable</code> to display the values in the
439      * <code>Vector</code> of <code>Vectors</code>, <code>rowData</code>,
440      * with column names, <code>columnNames</code>. The
441      * <code>Vectors</code> contained in <code>rowData</code>
442      * should contain the values for that row. In other words,
443      * the value of the cell at row 1, column 5 can be obtained
444      * with the following code:
445      * <p>
446      * <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre>
447      * <p>
448      * @param rowData the data for the new table
449      * @param columnNames names of each column
450      */

451     public JTable(Vector rowData, Vector columnNames) {
452         this(new DefaultTableModel(rowData, columnNames));
453     }
454
455     /**
456      * Constructs a <code>JTable</code> to display the values in the two dimensional array,
457      * <code>rowData</code>, with column names, <code>columnNames</code>.
458      * <code>rowData</code> is an array of rows, so the value of the cell at row 1,
459      * column 5 can be obtained with the following code:
460      * <p>
461      * <pre> rowData[1][5]; </pre>
462      * <p>
463      * All rows must be of the same length as <code>columnNames</code>.
464      * <p>
465      * @param rowData the data for the new table
466      * @param columnNames names of each column
467      */

468     public JTable(final Object JavaDoc[][] rowData, final Object JavaDoc[] columnNames) {
469         this(new AbstractTableModel() {
470             public String JavaDoc getColumnName(int column) { return columnNames[column].toString(); }
471             public int getRowCount() { return rowData.length; }
472             public int getColumnCount() { return columnNames.length; }
473             public Object JavaDoc getValueAt(int row, int col) { return rowData[row][col]; }
474             public boolean isCellEditable(int row, int column) { return true; }
475             public void setValueAt(Object JavaDoc value, int row, int col) {
476                 rowData[row][col] = value;
477                 fireTableCellUpdated(row, col);
478             }
479         });
480     }
481
482     /**
483      * Calls the <code>configureEnclosingScrollPane</code> method.
484      *
485      * @see #configureEnclosingScrollPane
486      */

487     public void addNotify() {
488         super.addNotify();
489         configureEnclosingScrollPane();
490     }
491
492     /**
493      * If this <code>JTable</code> is the <code>viewportView</code> of an enclosing <code>JScrollPane</code>
494      * (the usual situation), configure this <code>ScrollPane</code> by, amongst other things,
495      * installing the table's <code>tableHeader</code> as the <code>columnHeaderView</code> of the scroll pane.
496      * When a <code>JTable</code> is added to a <code>JScrollPane</code> in the usual way,
497      * using <code>new JScrollPane(myTable)</code>, <code>addNotify</code> is
498      * called in the <code>JTable</code> (when the table is added to the viewport).
499      * <code>JTable</code>'s <code>addNotify</code> method in turn calls this method,
500      * which is protected so that this default installation procedure can
501      * be overridden by a subclass.
502      *
503      * @see #addNotify
504      */

505     protected void configureEnclosingScrollPane() {
506         Container p = getParent();
507         if (p instanceof JViewport JavaDoc) {
508             Container gp = p.getParent();
509             if (gp instanceof JScrollPane JavaDoc) {
510                 JScrollPane JavaDoc scrollPane = (JScrollPane JavaDoc)gp;
511                 // Make certain we are the viewPort's view and not, for
512
// example, the rowHeaderView of the scrollPane -
513
// an implementor of fixed columns might do this.
514
JViewport JavaDoc viewport = scrollPane.getViewport();
515                 if (viewport == null || viewport.getView() != this) {
516                     return;
517                 }
518                 scrollPane.setColumnHeaderView(getTableHeader());
519         // scrollPane.getViewport().setBackingStoreEnabled(true);
520
Border border = scrollPane.getBorder();
521                 if (border == null || border instanceof UIResource) {
522                     scrollPane.setBorder(UIManager.getBorder("Table.scrollPaneBorder"));
523                 }
524             }
525         }
526     }
527
528     /**
529      * Calls the <code>unconfigureEnclosingScrollPane</code> method.
530      *
531      * @see #unconfigureEnclosingScrollPane
532      */

533     public void removeNotify() {
534         KeyboardFocusManager.getCurrentKeyboardFocusManager().
535             removePropertyChangeListener("permanentFocusOwner", editorRemover);
536     editorRemover = null;
537         unconfigureEnclosingScrollPane();
538         super.removeNotify();
539     }
540
541     /**
542      * Reverses the effect of <code>configureEnclosingScrollPane</code>
543      * by replacing the <code>columnHeaderView</code> of the enclosing
544      * scroll pane with <code>null</code>. <code>JTable</code>'s
545      * <code>removeNotify</code> method calls
546      * this method, which is protected so that this default uninstallation
547      * procedure can be overridden by a subclass.
548      *
549      * @see #removeNotify
550      * @see #configureEnclosingScrollPane
551      */

552     protected void unconfigureEnclosingScrollPane() {
553         Container p = getParent();
554         if (p instanceof JViewport JavaDoc) {
555             Container gp = p.getParent();
556             if (gp instanceof JScrollPane JavaDoc) {
557                 JScrollPane JavaDoc scrollPane = (JScrollPane JavaDoc)gp;
558                 // Make certain we are the viewPort's view and not, for
559
// example, the rowHeaderView of the scrollPane -
560
// an implementor of fixed columns might do this.
561
JViewport JavaDoc viewport = scrollPane.getViewport();
562                 if (viewport == null || viewport.getView() != this) {
563                     return;
564                 }
565                 scrollPane.setColumnHeaderView(null);
566             }
567         }
568     }
569
570     void setUIProperty(String JavaDoc propertyName, Object JavaDoc value) {
571         if (propertyName == "rowHeight") {
572             if (!isRowHeightSet) {
573                 setRowHeight(((Number JavaDoc)value).intValue());
574                 isRowHeightSet = false;
575             }
576             return;
577         }
578         super.setUIProperty(propertyName, value);
579     }
580
581 //
582
// Static Methods
583
//
584

585     /**
586      * Equivalent to <code>new JScrollPane(aTable)</code>.
587      *
588      * @deprecated As of Swing version 1.0.2,
589      * replaced by <code>new JScrollPane(aTable)</code>.
590      */

591     @Deprecated JavaDoc
592     static public JScrollPane JavaDoc createScrollPaneForTable(JTable JavaDoc aTable) {
593         return new JScrollPane JavaDoc(aTable);
594     }
595
596 //
597
// Table Attributes
598
//
599

600     /**
601      * Sets the <code>tableHeader</code> working with this <code>JTable</code> to <code>newHeader</code>.
602      * It is legal to have a <code>null</code> <code>tableHeader</code>.
603      *
604      * @param tableHeader new tableHeader
605      * @see #getTableHeader
606      * @beaninfo
607      * bound: true
608      * description: The JTableHeader instance which renders the column headers.
609      */

610     public void setTableHeader(JTableHeader tableHeader) {
611         if (this.tableHeader != tableHeader) {
612         JTableHeader old = this.tableHeader;
613             // Release the old header
614
if (old != null) {
615                 old.setTable(null);
616         }
617             this.tableHeader = tableHeader;
618             if (tableHeader != null) {
619                 tableHeader.setTable(this);
620         }
621         firePropertyChange("tableHeader", old, tableHeader);
622         }
623     }
624
625     /**
626      * Returns the <code>tableHeader</code> used by this <code>JTable</code>.
627      *
628      * @return the <code>tableHeader</code> used by this table
629      * @see #setTableHeader
630      */

631     public JTableHeader getTableHeader() {
632         return tableHeader;
633     }
634
635     /**
636      * Sets the height, in pixels, of all cells to <code>rowHeight</code>,
637      * revalidates, and repaints.
638      * The height of the cells will be equal to the row height minus
639      * the row margin.
640      *
641      * @param rowHeight new row height
642      * @exception IllegalArgumentException if <code>rowHeight</code> is
643      * less than 1
644      * @see #getRowHeight
645      * @beaninfo
646      * bound: true
647      * description: The height of the specified row.
648      */

649     public void setRowHeight(int rowHeight) {
650         if (rowHeight <= 0) {
651             throw new IllegalArgumentException JavaDoc("New row height less than 1");
652         }
653     int old = this.rowHeight;
654         this.rowHeight = rowHeight;
655     rowModel = null;
656         isRowHeightSet = true;
657         resizeAndRepaint();
658     firePropertyChange("rowHeight", old, rowHeight);
659     }
660
661     /**
662      * Returns the height of a table row, in pixels.
663      * The default row height is 16.0.
664      *
665      * @return the height in pixels of a table row
666      * @see #setRowHeight
667      */

668     public int getRowHeight() {
669         return rowHeight;
670     }
671
672     private SizeSequence JavaDoc getRowModel() {
673     if (rowModel == null) {
674         rowModel = new SizeSequence JavaDoc(getRowCount(), getRowHeight());
675     }
676     return rowModel;
677     }
678
679     /**
680      * Sets the height for <code>row</code> to <code>rowHeight</code>,
681      * revalidates, and repaints. The height of the cells in this row
682      * will be equal to the row height minus the row margin.
683      *
684      * @param row the row whose height is being
685                         changed
686      * @param rowHeight new row height, in pixels
687      * @exception IllegalArgumentException if <code>rowHeight</code> is
688      * less than 1
689      * @beaninfo
690      * bound: true
691      * description: The height in pixels of the cells in <code>row</code>
692      */

693     public void setRowHeight(int row, int rowHeight) {
694         if (rowHeight <= 0) {
695             throw new IllegalArgumentException JavaDoc("New row height less than 1");
696         }
697     getRowModel().setSize(row, rowHeight);
698     resizeAndRepaint();
699     }
700
701     /**
702      * Returns the height, in pixels, of the cells in <code>row</code>.
703      * @param row the row whose height is to be returned
704      * @return the height, in pixels, of the cells in the row
705      */

706     public int getRowHeight(int row) {
707     return (rowModel == null) ? getRowHeight() : rowModel.getSize(row);
708     }
709
710     /**
711      * Sets the amount of empty space between cells in adjacent rows.
712      *
713      * @param rowMargin the number of pixels between cells in a row
714      * @see #getRowMargin
715      * @beaninfo
716      * bound: true
717      * description: The amount of space between cells.
718      */

719     public void setRowMargin(int rowMargin) {
720     int old = this.rowMargin;
721         this.rowMargin = rowMargin;
722         resizeAndRepaint();
723     firePropertyChange("rowMargin", old, rowMargin);
724     }
725
726     /**
727      * Gets the amount of empty space, in pixels, between cells. Equivalent to:
728      * <code>getIntercellSpacing().height</code>.
729      * @return the number of pixels between cells in a row
730      *
731      * @see #setRowMargin
732      */

733     public int getRowMargin() {
734         return rowMargin;
735     }
736
737     /**
738      * Sets the <code>rowMargin</code> and the <code>columnMargin</code> --
739      * the height and width of the space between cells -- to
740      * <code>intercellSpacing</code>.
741      *
742      * @param intercellSpacing a <code>Dimension</code>
743      * specifying the new width
744      * and height between cells
745      * @see #getIntercellSpacing
746      * @beaninfo
747      * description: The spacing between the cells,
748      * drawn in the background color of the JTable.
749      */

750     public void setIntercellSpacing(Dimension intercellSpacing) {
751         // Set the rowMargin here and columnMargin in the TableColumnModel
752
setRowMargin(intercellSpacing.height);
753         getColumnModel().setColumnMargin(intercellSpacing.width);
754
755         resizeAndRepaint();
756     }
757
758     /**
759      * Returns the horizontal and vertical space between cells.
760      * The default spacing is (1, 1), which provides room to draw the grid.
761      *
762      * @return the horizontal and vertical spacing between cells
763      * @see #setIntercellSpacing
764      */

765     public Dimension getIntercellSpacing() {
766         return new Dimension(getColumnModel().getColumnMargin(), rowMargin);
767     }
768
769     /**
770      * Sets the color used to draw grid lines to <code>gridColor</code> and redisplays.
771      * The default color is look and feel dependent.
772      *
773      * @param gridColor the new color of the grid lines
774      * @exception IllegalArgumentException if <code>gridColor</code> is <code>null</code>
775      * @see #getGridColor
776      * @beaninfo
777      * bound: true
778      * description: The grid color.
779      */

780     public void setGridColor(Color gridColor) {
781         if (gridColor == null) {
782             throw new IllegalArgumentException JavaDoc("New color is null");
783         }
784     Color old = this.gridColor;
785         this.gridColor = gridColor;
786     firePropertyChange("gridColor", old, gridColor);
787         // Redraw
788
repaint();
789     }
790
791     /**
792      * Returns the color used to draw grid lines.
793      * The default color is look and feel dependent.
794      *
795      * @return the color used to draw grid lines
796      * @see #setGridColor
797      */

798     public Color getGridColor() {
799         return gridColor;
800     }
801
802     /**
803      * Sets whether the table draws grid lines around cells.
804      * If <code>showGrid</code> is true it does; if it is false it doesn't.
805      * There is no <code>getShowGrid</code> method as this state is held
806      * in two variables -- <code>showHorizontalLines</code> and <code>showVerticalLines</code> --
807      * each of which can be queried independently.
808      *
809      * @param showGrid true if table view should draw grid lines
810      *
811      * @see #setShowVerticalLines
812      * @see #setShowHorizontalLines
813      * @beaninfo
814      * description: The color used to draw the grid lines.
815      */

816     public void setShowGrid(boolean showGrid) {
817         setShowHorizontalLines(showGrid);
818         setShowVerticalLines(showGrid);
819
820         // Redraw
821
repaint();
822     }
823
824     /**
825      * Sets whether the table draws horizontal lines between cells.
826      * If <code>showHorizontalLines</code> is true it does; if it is false it doesn't.
827      *
828      * @param showHorizontalLines true if table view should draw horizontal lines
829      * @see #getShowHorizontalLines
830      * @see #setShowGrid
831      * @see #setShowVerticalLines
832      * @beaninfo
833      * bound: true
834      * description: Whether horizontal lines should be drawn in between the cells.
835      */

836     public void setShowHorizontalLines(boolean showHorizontalLines) {
837         boolean old = this.showHorizontalLines;
838     this.showHorizontalLines = showHorizontalLines;
839     firePropertyChange("showHorizontalLines", old, showHorizontalLines);
840
841         // Redraw
842
repaint();
843     }
844
845     /**
846      * Sets whether the table draws vertical lines between cells.
847      * If <code>showVerticalLines</code> is true it does; if it is false it doesn't.
848      *
849      * @param showVerticalLines true if table view should draw vertical lines
850      * @see #getShowVerticalLines
851      * @see #setShowGrid
852      * @see #setShowHorizontalLines
853      * @beaninfo
854      * bound: true
855      * description: Whether vertical lines should be drawn in between the cells.
856      */

857     public void setShowVerticalLines(boolean showVerticalLines) {
858         boolean old = this.showVerticalLines;
859     this.showVerticalLines = showVerticalLines;
860     firePropertyChange("showVerticalLines", old, showVerticalLines);
861         // Redraw
862
repaint();
863     }
864
865     /**
866      * Returns true if the table draws horizontal lines between cells, false if it
867      * doesn't. The default is true.
868      *
869      * @return true if the table draws horizontal lines between cells, false if it
870      * doesn't
871      * @see #setShowHorizontalLines
872      */

873     public boolean getShowHorizontalLines() {
874         return showHorizontalLines;
875     }
876
877     /**
878      * Returns true if the table draws vertical lines between cells, false if it
879      * doesn't. The default is true.
880      *
881      * @return true if the table draws vertical lines between cells, false if it
882      * doesn't
883      * @see #setShowVerticalLines
884      */

885     public boolean getShowVerticalLines() {
886         return showVerticalLines;
887     }
888
889     /**
890      * Sets the table's auto resize mode when the table is resized.
891      *
892      * @param mode One of 5 legal values:
893      * AUTO_RESIZE_OFF,
894      * AUTO_RESIZE_NEXT_COLUMN,
895      * AUTO_RESIZE_SUBSEQUENT_COLUMNS,
896      * AUTO_RESIZE_LAST_COLUMN,
897      * AUTO_RESIZE_ALL_COLUMNS
898      *
899      * @see #getAutoResizeMode
900      * @see #doLayout
901      * @beaninfo
902      * bound: true
903      * description: Whether the columns should adjust themselves automatically.
904      * enum: AUTO_RESIZE_OFF JTable.AUTO_RESIZE_OFF
905      * AUTO_RESIZE_NEXT_COLUMN JTable.AUTO_RESIZE_NEXT_COLUMN
906      * AUTO_RESIZE_SUBSEQUENT_COLUMNS JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS
907      * AUTO_RESIZE_LAST_COLUMN JTable.AUTO_RESIZE_LAST_COLUMN
908      * AUTO_RESIZE_ALL_COLUMNS JTable.AUTO_RESIZE_ALL_COLUMNS
909      */

910     public void setAutoResizeMode(int mode) {
911         if ((mode == AUTO_RESIZE_OFF) ||
912             (mode == AUTO_RESIZE_NEXT_COLUMN) ||
913             (mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) ||
914             (mode == AUTO_RESIZE_LAST_COLUMN) ||
915             (mode == AUTO_RESIZE_ALL_COLUMNS)) {
916         int old = autoResizeMode;
917             autoResizeMode = mode;
918             resizeAndRepaint();
919             if (tableHeader != null) {
920         tableHeader.resizeAndRepaint();
921         }
922         firePropertyChange("autoResizeMode", old, autoResizeMode);
923         }
924     }
925
926     /**
927      * Returns the auto resize mode of the table. The default mode
928      * is AUTO_RESIZE_SUBSEQUENT_COLUMNS.
929      *
930      * @return the autoResizeMode of the table
931      *
932      * @see #setAutoResizeMode
933      * @see #doLayout
934      */

935     public int getAutoResizeMode() {
936         return autoResizeMode;
937     }
938
939     /**
940      * Sets this table's <code>autoCreateColumnsFromModel</code> flag.
941      * This method calls <code>createDefaultColumnsFromModel</code> if
942      * <code>autoCreateColumnsFromModel</code> changes from false to true.
943      *
944      * @param autoCreateColumnsFromModel true if <code>JTable</code> should automatically create columns
945      * @see #getAutoCreateColumnsFromModel
946      * @see #createDefaultColumnsFromModel
947      * @beaninfo
948      * bound: true
949      * description: Automatically populates the columnModel when a new TableModel is submitted.
950      */

951     public void setAutoCreateColumnsFromModel(boolean autoCreateColumnsFromModel) {
952         if (this.autoCreateColumnsFromModel != autoCreateColumnsFromModel) {
953         boolean old = this.autoCreateColumnsFromModel;
954             this.autoCreateColumnsFromModel = autoCreateColumnsFromModel;
955             if (autoCreateColumnsFromModel) {
956                 createDefaultColumnsFromModel();
957         }
958         firePropertyChange("autoCreateColumnsFromModel", old, autoCreateColumnsFromModel);
959         }
960     }
961
962     /**
963      * Determines whether the table will create default columns from the model.
964      * If true, <code>setModel</code> will clear any existing columns and
965      * create new columns from the new model. Also, if the event in
966      * the <code>tableChanged</code> notification specifies that the
967      * entire table changed, then the columns will be rebuilt.
968      * The default is true.
969      *
970      * @return the autoCreateColumnsFromModel of the table
971      * @see #setAutoCreateColumnsFromModel
972      * @see #createDefaultColumnsFromModel
973      */

974     public boolean getAutoCreateColumnsFromModel() {
975         return autoCreateColumnsFromModel;
976     }
977
978     /**
979      * Creates default columns for the table from
980      * the data model using the <code>getColumnCount</code> method
981      * defined in the <code>TableModel</code> interface.
982      * <p>
983      * Clears any existing columns before creating the
984      * new columns based on information from the model.
985      *
986      * @see #getAutoCreateColumnsFromModel
987      */

988     public void createDefaultColumnsFromModel() {
989         TableModel m = getModel();
990         if (m != null) {
991             // Remove any current columns
992
TableColumnModel cm = getColumnModel();
993             while (cm.getColumnCount() > 0) {
994                 cm.removeColumn(cm.getColumn(0));
995         }
996
997             // Create new columns from the data model info
998
for (int i = 0; i < m.getColumnCount(); i++) {
999                 TableColumn newColumn = new TableColumn(i);
1000                addColumn(newColumn);
1001            }
1002        }
1003    }
1004
1005    /**
1006     * Sets a default cell renderer to be used if no renderer has been set in
1007     * a <code>TableColumn</code>. If renderer is <code>null</code>,
1008     * removes the default renderer for this column class.
1009     *
1010