5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javax.swing;
27
28 import java.util.*;
29
30 import java.applet.Applet;
31 import java.awt.*;
32 import java.awt.event.*;
33 import java.awt.print.*;
34
35 import java.beans.*;
36
37 import java.io.ObjectOutputStream;
38 import java.io.ObjectInputStream;
39 import java.io.IOException;
40 import java.io.InvalidObjectException;
41
42 import javax.accessibility.*;
43
44 import javax.swing.event.*;
45 import javax.swing.plaf.*;
46 import javax.swing.table.*;
47 import javax.swing.border.*;
48
49 import java.text.NumberFormat;
50 import java.text.DateFormat;
51 import java.text.MessageFormat;
52
53 import javax.print.attribute.*;
54 import javax.print.PrintService;
55 import sun.reflect.misc.ReflectUtil;
56
57 import sun.swing.SwingUtilities2;
58 import sun.swing.SwingUtilities2.Section;
59 import static sun.swing.SwingUtilities2.Section.*;
60 import sun.swing.PrintingStatus;
61
62 /**
63 * The <code>JTable</code> is used to display and edit regular two-dimensional tables
64 * of cells.
65 * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/table.html">How to Use Tables</a>
66 * in <em>The Java Tutorial</em>
67 * for task-oriented documentation and examples of using <code>JTable</code>.
68 *
69 * <p>
70 * The <code>JTable</code> has many
71 * facilities that make it possible to customize its rendering and editing
72 * but provides defaults for these features so that simple tables can be
73 * set up easily. For example, to set up a table with 10 rows and 10
74 * columns of numbers:
187 * <p>
188 * As for all <code>JComponent</code> classes, you can use
189 * {@link InputMap} and {@link ActionMap} to associate an
190 * {@link Action} object with a {@link KeyStroke} and execute the
191 * action under specified conditions.
192 * <p>
193 * <strong>Warning:</strong> Swing is not thread safe. For more
194 * information see <a
195 * href="package-summary.html#threading">Swing's Threading
196 * Policy</a>.
197 * <p>
198 * <strong>Warning:</strong>
199 * Serialized objects of this class will not be compatible with
200 * future Swing releases. The current serialization support is
201 * appropriate for short term storage or RMI between applications running
202 * the same version of Swing. As of 1.4, support for long term storage
203 * of all JavaBeans™
204 * has been added to the <code>java.beans</code> package.
205 * Please see {@link java.beans.XMLEncoder}.
206 *
207 *
208 * @beaninfo
209 * attribute: isContainer false
210 * description: A component which displays data in a two dimensional grid.
211 *
212 * @author Philip Milne
213 * @author Shannon Hickey (printing support)
214 * @see javax.swing.table.DefaultTableModel
215 * @see javax.swing.table.TableRowSorter
216 * @since 1.2
217 */
218 /* The first versions of the JTable, contained in Swing-0.1 through
219 * Swing-0.4, were written by Alan Chung.
220 */
221 @SuppressWarnings("serial") // Same-version serialization only
222 public class JTable extends JComponent implements TableModelListener, Scrollable,
223 TableColumnModelListener, ListSelectionListener, CellEditorListener,
224 Accessible, RowSorterListener
225 {
226 //
227 // Static Constants
228 //
229
230 /**
231 * @see #getUIClassID
232 * @see #readObject
233 */
234 private static final String uiClassID = "TableUI";
235
236 /** Do not adjust column widths automatically; use a horizontal scrollbar instead. */
237 public static final int AUTO_RESIZE_OFF = 0;
238
239 /** When a column is adjusted in the UI, adjust the next column the opposite way. */
240 public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
873 * @param aTable a {@code JTable} to be used for the scroll pane
874 * @return a {@code JScrollPane} created using {@code aTable}
875 * @deprecated As of Swing version 1.0.2,
876 * replaced by <code>new JScrollPane(aTable)</code>.
877 */
878 @Deprecated
879 static public JScrollPane createScrollPaneForTable(JTable aTable) {
880 return new JScrollPane(aTable);
881 }
882
883 //
884 // Table Attributes
885 //
886
887 /**
888 * Sets the <code>tableHeader</code> working with this <code>JTable</code> to <code>newHeader</code>.
889 * It is legal to have a <code>null</code> <code>tableHeader</code>.
890 *
891 * @param tableHeader new tableHeader
892 * @see #getTableHeader
893 * @beaninfo
894 * bound: true
895 * description: The JTableHeader instance which renders the column headers.
896 */
897 public void setTableHeader(JTableHeader tableHeader) {
898 if (this.tableHeader != tableHeader) {
899 JTableHeader old = this.tableHeader;
900 // Release the old header
901 if (old != null) {
902 old.setTable(null);
903 }
904 this.tableHeader = tableHeader;
905 if (tableHeader != null) {
906 tableHeader.setTable(this);
907 }
908 firePropertyChange("tableHeader", old, tableHeader);
909 }
910 }
911
912 /**
913 * Returns the <code>tableHeader</code> used by this <code>JTable</code>.
914 *
915 * @return the <code>tableHeader</code> used by this table
916 * @see #setTableHeader
917 */
918 public JTableHeader getTableHeader() {
919 return tableHeader;
920 }
921
922 /**
923 * Sets the height, in pixels, of all cells to <code>rowHeight</code>,
924 * revalidates, and repaints.
925 * The height of the cells will be equal to the row height minus
926 * the row margin.
927 *
928 * @param rowHeight new row height
929 * @exception IllegalArgumentException if <code>rowHeight</code> is
930 * less than 1
931 * @see #getRowHeight
932 * @beaninfo
933 * bound: true
934 * description: The height of the specified row.
935 */
936 public void setRowHeight(int rowHeight) {
937 if (rowHeight <= 0) {
938 throw new IllegalArgumentException("New row height less than 1");
939 }
940 int old = this.rowHeight;
941 this.rowHeight = rowHeight;
942 rowModel = null;
943 if (sortManager != null) {
944 sortManager.modelRowSizes = null;
945 }
946 isRowHeightSet = true;
947 resizeAndRepaint();
948 firePropertyChange("rowHeight", old, rowHeight);
949 }
950
951 /**
952 * Returns the height of a table row, in pixels.
953 *
954 * @return the height in pixels of a table row
955 * @see #setRowHeight
958 return rowHeight;
959 }
960
961 private SizeSequence getRowModel() {
962 if (rowModel == null) {
963 rowModel = new SizeSequence(getRowCount(), getRowHeight());
964 }
965 return rowModel;
966 }
967
968 /**
969 * Sets the height for <code>row</code> to <code>rowHeight</code>,
970 * revalidates, and repaints. The height of the cells in this row
971 * will be equal to the row height minus the row margin.
972 *
973 * @param row the row whose height is being
974 changed
975 * @param rowHeight new row height, in pixels
976 * @exception IllegalArgumentException if <code>rowHeight</code> is
977 * less than 1
978 * @beaninfo
979 * bound: true
980 * description: The height in pixels of the cells in <code>row</code>
981 * @since 1.3
982 */
983 public void setRowHeight(int row, int rowHeight) {
984 if (rowHeight <= 0) {
985 throw new IllegalArgumentException("New row height less than 1");
986 }
987 getRowModel().setSize(row, rowHeight);
988 if (sortManager != null) {
989 sortManager.setViewRowHeight(row, rowHeight);
990 }
991 resizeAndRepaint();
992 }
993
994 /**
995 * Returns the height, in pixels, of the cells in <code>row</code>.
996 * @param row the row whose height is to be returned
997 * @return the height, in pixels, of the cells in the row
998 * @since 1.3
999 */
1000 public int getRowHeight(int row) {
1001 return (rowModel == null) ? getRowHeight() : rowModel.getSize(row);
1002 }
1003
1004 /**
1005 * Sets the amount of empty space between cells in adjacent rows.
1006 *
1007 * @param rowMargin the number of pixels between cells in a row
1008 * @see #getRowMargin
1009 * @beaninfo
1010 * bound: true
1011 * description: The amount of space between cells.
1012 */
1013 public void setRowMargin(int rowMargin) {
1014 int old = this.rowMargin;
1015 this.rowMargin = rowMargin;
1016 resizeAndRepaint();
1017 firePropertyChange("rowMargin", old, rowMargin);
1018 }
1019
1020 /**
1021 * Gets the amount of empty space, in pixels, between cells. Equivalent to:
1022 * <code>getIntercellSpacing().height</code>.
1023 * @return the number of pixels between cells in a row
1024 *
1025 * @see #setRowMargin
1026 */
1027 public int getRowMargin() {
1028 return rowMargin;
1029 }
1030
1031 /**
1032 * Sets the <code>rowMargin</code> and the <code>columnMargin</code> --
1033 * the height and width of the space between cells -- to
1034 * <code>intercellSpacing</code>.
1035 *
1036 * @param intercellSpacing a <code>Dimension</code>
1037 * specifying the new width
1038 * and height between cells
1039 * @see #getIntercellSpacing
1040 * @beaninfo
1041 * description: The spacing between the cells,
1042 * drawn in the background color of the JTable.
1043 */
1044 public void setIntercellSpacing(Dimension intercellSpacing) {
1045 // Set the rowMargin here and columnMargin in the TableColumnModel
1046 setRowMargin(intercellSpacing.height);
1047 getColumnModel().setColumnMargin(intercellSpacing.width);
1048
1049 resizeAndRepaint();
1050 }
1051
1052 /**
1053 * Returns the horizontal and vertical space between cells.
1054 * The default spacing is look and feel dependent.
1055 *
1056 * @return the horizontal and vertical spacing between cells
1057 * @see #setIntercellSpacing
1058 */
1059 public Dimension getIntercellSpacing() {
1060 return new Dimension(getColumnModel().getColumnMargin(), rowMargin);
1061 }
1062
1063 /**
1064 * Sets the color used to draw grid lines to <code>gridColor</code> and redisplays.
1065 * The default color is look and feel dependent.
1066 *
1067 * @param gridColor the new color of the grid lines
1068 * @exception IllegalArgumentException if <code>gridColor</code> is <code>null</code>
1069 * @see #getGridColor
1070 * @beaninfo
1071 * bound: true
1072 * description: The grid color.
1073 */
1074 public void setGridColor(Color gridColor) {
1075 if (gridColor == null) {
1076 throw new IllegalArgumentException("New color is null");
1077 }
1078 Color old = this.gridColor;
1079 this.gridColor = gridColor;
1080 firePropertyChange("gridColor", old, gridColor);
1081 // Redraw
1082 repaint();
1083 }
1084
1085 /**
1086 * Returns the color used to draw grid lines.
1087 * The default color is look and feel dependent.
1088 *
1089 * @return the color used to draw grid lines
1090 * @see #setGridColor
1091 */
1092 public Color getGridColor() {
1093 return gridColor;
1094 }
1095
1096 /**
1097 * Sets whether the table draws grid lines around cells.
1098 * If <code>showGrid</code> is true it does; if it is false it doesn't.
1099 * There is no <code>getShowGrid</code> method as this state is held
1100 * in two variables -- <code>showHorizontalLines</code> and <code>showVerticalLines</code> --
1101 * each of which can be queried independently.
1102 *
1103 * @param showGrid true if table view should draw grid lines
1104 *
1105 * @see #setShowVerticalLines
1106 * @see #setShowHorizontalLines
1107 * @beaninfo
1108 * description: The color used to draw the grid lines.
1109 */
1110 public void setShowGrid(boolean showGrid) {
1111 setShowHorizontalLines(showGrid);
1112 setShowVerticalLines(showGrid);
1113
1114 // Redraw
1115 repaint();
1116 }
1117
1118 /**
1119 * Sets whether the table draws horizontal lines between cells.
1120 * If <code>showHorizontalLines</code> is true it does; if it is false it doesn't.
1121 *
1122 * @param showHorizontalLines true if table view should draw horizontal lines
1123 * @see #getShowHorizontalLines
1124 * @see #setShowGrid
1125 * @see #setShowVerticalLines
1126 * @beaninfo
1127 * bound: true
1128 * description: Whether horizontal lines should be drawn in between the cells.
1129 */
1130 public void setShowHorizontalLines(boolean showHorizontalLines) {
1131 boolean old = this.showHorizontalLines;
1132 this.showHorizontalLines = showHorizontalLines;
1133 firePropertyChange("showHorizontalLines", old, showHorizontalLines);
1134
1135 // Redraw
1136 repaint();
1137 }
1138
1139 /**
1140 * Sets whether the table draws vertical lines between cells.
1141 * If <code>showVerticalLines</code> is true it does; if it is false it doesn't.
1142 *
1143 * @param showVerticalLines true if table view should draw vertical lines
1144 * @see #getShowVerticalLines
1145 * @see #setShowGrid
1146 * @see #setShowHorizontalLines
1147 * @beaninfo
1148 * bound: true
1149 * description: Whether vertical lines should be drawn in between the cells.
1150 */
1151 public void setShowVerticalLines(boolean showVerticalLines) {
1152 boolean old = this.showVerticalLines;
1153 this.showVerticalLines = showVerticalLines;
1154 firePropertyChange("showVerticalLines", old, showVerticalLines);
1155 // Redraw
1156 repaint();
1157 }
1158
1159 /**
1160 * Returns true if the table draws horizontal lines between cells, false if it
1161 * doesn't. The default value is look and feel dependent.
1162 *
1163 * @return true if the table draws horizontal lines between cells, false if it
1164 * doesn't
1165 * @see #setShowHorizontalLines
1166 */
1167 public boolean getShowHorizontalLines() {
1168 return showHorizontalLines;
1169 }
1170
1177 * @see #setShowVerticalLines
1178 */
1179 public boolean getShowVerticalLines() {
1180 return showVerticalLines;
1181 }
1182
1183 /**
1184 * Sets the table's auto resize mode when the table is resized. For further
1185 * information on how the different resize modes work, see
1186 * {@link #doLayout}.
1187 *
1188 * @param mode One of 5 legal values:
1189 * AUTO_RESIZE_OFF,
1190 * AUTO_RESIZE_NEXT_COLUMN,
1191 * AUTO_RESIZE_SUBSEQUENT_COLUMNS,
1192 * AUTO_RESIZE_LAST_COLUMN,
1193 * AUTO_RESIZE_ALL_COLUMNS
1194 *
1195 * @see #getAutoResizeMode
1196 * @see #doLayout
1197 * @beaninfo
1198 * bound: true
1199 * description: Whether the columns should adjust themselves automatically.
1200 * enum: AUTO_RESIZE_OFF JTable.AUTO_RESIZE_OFF
1201 * AUTO_RESIZE_NEXT_COLUMN JTable.AUTO_RESIZE_NEXT_COLUMN
1202 * AUTO_RESIZE_SUBSEQUENT_COLUMNS JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS
1203 * AUTO_RESIZE_LAST_COLUMN JTable.AUTO_RESIZE_LAST_COLUMN
1204 * AUTO_RESIZE_ALL_COLUMNS JTable.AUTO_RESIZE_ALL_COLUMNS
1205 */
1206 public void setAutoResizeMode(int mode) {
1207 if (isValidAutoResizeMode(mode)) {
1208 int old = autoResizeMode;
1209 autoResizeMode = mode;
1210 resizeAndRepaint();
1211 if (tableHeader != null) {
1212 tableHeader.resizeAndRepaint();
1213 }
1214 firePropertyChange("autoResizeMode", old, autoResizeMode);
1215 }
1216 }
1217
1218 private static boolean isValidAutoResizeMode(int mode) {
1219 return (mode == AUTO_RESIZE_OFF)
1220 || (mode == AUTO_RESIZE_NEXT_COLUMN)
1221 || (mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS)
1222 || (mode == AUTO_RESIZE_LAST_COLUMN)
1223 || (mode == AUTO_RESIZE_ALL_COLUMNS);
1224 }
1225
1227 * Returns the auto resize mode of the table. The default mode
1228 * is AUTO_RESIZE_SUBSEQUENT_COLUMNS.
1229 *
1230 * @return the autoResizeMode of the table
1231 *
1232 * @see #setAutoResizeMode
1233 * @see #doLayout
1234 */
1235 public int getAutoResizeMode() {
1236 return autoResizeMode;
1237 }
1238
1239 /**
1240 * Sets this table's <code>autoCreateColumnsFromModel</code> flag.
1241 * This method calls <code>createDefaultColumnsFromModel</code> if
1242 * <code>autoCreateColumnsFromModel</code> changes from false to true.
1243 *
1244 * @param autoCreateColumnsFromModel true if <code>JTable</code> should automatically create columns
1245 * @see #getAutoCreateColumnsFromModel
1246 * @see #createDefaultColumnsFromModel
1247 * @beaninfo
1248 * bound: true
1249 * description: Automatically populates the columnModel when a new TableModel is submitted.
1250 */
1251 public void setAutoCreateColumnsFromModel(boolean autoCreateColumnsFromModel) {
1252 if (this.autoCreateColumnsFromModel != autoCreateColumnsFromModel) {
1253 boolean old = this.autoCreateColumnsFromModel;
1254 this.autoCreateColumnsFromModel = autoCreateColumnsFromModel;
1255 if (autoCreateColumnsFromModel) {
1256 createDefaultColumnsFromModel();
1257 }
1258 firePropertyChange("autoCreateColumnsFromModel", old, autoCreateColumnsFromModel);
1259 }
1260 }
1261
1262 /**
1263 * Determines whether the table will create default columns from the model.
1264 * If true, <code>setModel</code> will clear any existing columns and
1265 * create new columns from the new model. Also, if the event in
1266 * the <code>tableChanged</code> notification specifies that the
1267 * entire table changed, then the columns will be rebuilt.
1268 * The default is true.
1269 *
1270 * @return the autoCreateColumnsFromModel of the table
1421 * feels (including those that subclass {@code BasicLookAndFeel}) begin a
1422 * drag and drop operation whenever the user presses the mouse button over
1423 * an item (in single selection mode) or a selection (in other selection
1424 * modes) and then moves the mouse a few pixels. Setting this property to
1425 * {@code true} can therefore have a subtle effect on how selections behave.
1426 * <p>
1427 * If a look and feel is used that ignores this property, you can still
1428 * begin a drag and drop operation by calling {@code exportAsDrag} on the
1429 * table's {@code TransferHandler}.
1430 *
1431 * @param b whether or not to enable automatic drag handling
1432 * @exception HeadlessException if
1433 * <code>b</code> is <code>true</code> and
1434 * <code>GraphicsEnvironment.isHeadless()</code>
1435 * returns <code>true</code>
1436 * @see java.awt.GraphicsEnvironment#isHeadless
1437 * @see #getDragEnabled
1438 * @see #setTransferHandler
1439 * @see TransferHandler
1440 * @since 1.4
1441 *
1442 * @beaninfo
1443 * description: determines whether automatic drag handling is enabled
1444 * bound: false
1445 */
1446 public void setDragEnabled(boolean b) {
1447 checkDragEnabled(b);
1448 dragEnabled = b;
1449 }
1450
1451 private void checkDragEnabled(boolean b) {
1452 if (b && GraphicsEnvironment.isHeadless()) {
1453 throw new HeadlessException();
1454 }
1455 }
1456
1457 /**
1458 * Returns whether or not automatic drag handling is enabled.
1459 *
1460 * @return the value of the {@code dragEnabled} property
1461 * @see #setDragEnabled
1462 * @since 1.4
1463 */
1464 public boolean getDragEnabled() {
1465 return dragEnabled;
1813 }
1814
1815 /**
1816 * Returns the location that this component should visually indicate
1817 * as the drop location during a DnD operation over the component,
1818 * or {@code null} if no location is to currently be shown.
1819 * <p>
1820 * This method is not meant for querying the drop location
1821 * from a {@code TransferHandler}, as the drop location is only
1822 * set after the {@code TransferHandler}'s <code>canImport</code>
1823 * has returned and has allowed for the location to be shown.
1824 * <p>
1825 * When this property changes, a property change event with
1826 * name "dropLocation" is fired by the component.
1827 *
1828 * @return the drop location
1829 * @see #setDropMode
1830 * @see TransferHandler#canImport(TransferHandler.TransferSupport)
1831 * @since 1.6
1832 */
1833 public final DropLocation getDropLocation() {
1834 return dropLocation;
1835 }
1836
1837 /**
1838 * Specifies whether a {@code RowSorter} should be created for the
1839 * table whenever its model changes.
1840 * <p>
1841 * When {@code setAutoCreateRowSorter(true)} is invoked, a {@code
1842 * TableRowSorter} is immediately created and installed on the
1843 * table. While the {@code autoCreateRowSorter} property remains
1844 * {@code true}, every time the model is changed, a new {@code
1845 * TableRowSorter} is created and set as the table's row sorter.
1846 * The default value for the {@code autoCreateRowSorter}
1847 * property is {@code false}.
1848 *
1849 * @param autoCreateRowSorter whether or not a {@code RowSorter}
1850 * should be automatically created
1851 * @see javax.swing.table.TableRowSorter
1852 * @beaninfo
1853 * bound: true
1854 * preferred: true
1855 * description: Whether or not to turn on sorting by default.
1856 * @since 1.6
1857 */
1858 public void setAutoCreateRowSorter(boolean autoCreateRowSorter) {
1859 boolean oldValue = this.autoCreateRowSorter;
1860 this.autoCreateRowSorter = autoCreateRowSorter;
1861 if (autoCreateRowSorter) {
1862 setRowSorter(new TableRowSorter<TableModel>(getModel()));
1863 }
1864 firePropertyChange("autoCreateRowSorter", oldValue,
1865 autoCreateRowSorter);
1866 }
1867
1868 /**
1869 * Returns {@code true} if whenever the model changes, a new
1870 * {@code RowSorter} should be created and installed
1871 * as the table's sorter; otherwise, returns {@code false}.
1872 *
1873 * @return true if a {@code RowSorter} should be created when
1874 * the model changes
1875 * @since 1.6
1876 */
1877 public boolean getAutoCreateRowSorter() {
1878 return autoCreateRowSorter;
1879 }
1880
1881 /**
1882 * Specifies whether the selection should be updated after sorting.
1883 * If true, on sorting the selection is reset such that
1884 * the same rows, in terms of the model, remain selected. The default
1885 * is true.
1886 *
1887 * @param update whether or not to update the selection on sorting
1888 * @beaninfo
1889 * bound: true
1890 * expert: true
1891 * description: Whether or not to update the selection on sorting
1892 * @since 1.6
1893 */
1894 public void setUpdateSelectionOnSort(boolean update) {
1895 if (updateSelectionOnSort != update) {
1896 updateSelectionOnSort = update;
1897 firePropertyChange("updateSelectionOnSort", !update, update);
1898 }
1899 }
1900
1901 /**
1902 * Returns true if the selection should be updated after sorting.
1903 *
1904 * @return whether to update the selection on a sort
1905 * @since 1.6
1906 */
1907 public boolean getUpdateSelectionOnSort() {
1908 return updateSelectionOnSort;
1909 }
1910
1911 /**
1912 * Sets the <code>RowSorter</code>. <code>RowSorter</code> is used
1913 * to provide sorting and filtering to a <code>JTable</code>.
1914 * <p>
1915 * This method clears the selection and resets any variable row heights.
1916 * <p>
1917 * This method fires a <code>PropertyChangeEvent</code> when appropriate,
1918 * with the property name <code>"rowSorter"</code>. For
1919 * backward-compatibility, this method fires an additional event with the
1920 * property name <code>"sorter"</code>.
1921 * <p>
1922 * If the underlying model of the <code>RowSorter</code> differs from
1923 * that of this <code>JTable</code> undefined behavior will result.
1924 *
1925 * @param sorter the <code>RowSorter</code>; <code>null</code> turns
1926 * sorting off
1927 * @see javax.swing.table.TableRowSorter
1928 * @beaninfo
1929 * bound: true
1930 * description: The table's RowSorter
1931 * @since 1.6
1932 */
1933 public void setRowSorter(RowSorter<? extends TableModel> sorter) {
1934 RowSorter<? extends TableModel> oldRowSorter = null;
1935 if (sortManager != null) {
1936 oldRowSorter = sortManager.sorter;
1937 sortManager.dispose();
1938 sortManager = null;
1939 }
1940 rowModel = null;
1941 clearSelectionAndLeadAnchor();
1942 if (sorter != null) {
1943 sortManager = new SortManager(sorter);
1944 }
1945 resizeAndRepaint();
1946 firePropertyChange("rowSorter", oldRowSorter, sorter);
1947 firePropertyChange("sorter", oldRowSorter, sorter);
1948 }
1949
1950 /**
1951 * Returns the object responsible for sorting.
1952 *
1964 * Sets the table's selection mode to allow only single selections, a single
1965 * contiguous interval, or multiple intervals.
1966 * <P>
1967 * <b>Note:</b>
1968 * <code>JTable</code> provides all the methods for handling
1969 * column and row selection. When setting states,
1970 * such as <code>setSelectionMode</code>, it not only
1971 * updates the mode for the row selection model but also sets similar
1972 * values in the selection model of the <code>columnModel</code>.
1973 * If you want to have the row and column selection models operating
1974 * in different modes, set them both directly.
1975 * <p>
1976 * Both the row and column selection models for <code>JTable</code>
1977 * default to using a <code>DefaultListSelectionModel</code>
1978 * so that <code>JTable</code> works the same way as the
1979 * <code>JList</code>. See the <code>setSelectionMode</code> method
1980 * in <code>JList</code> for details about the modes.
1981 *
1982 * @param selectionMode the mode used by the row and column selection models
1983 * @see JList#setSelectionMode
1984 * @beaninfo
1985 * description: The selection mode used by the row and column selection models.
1986 * enum: SINGLE_SELECTION ListSelectionModel.SINGLE_SELECTION
1987 * SINGLE_INTERVAL_SELECTION ListSelectionModel.SINGLE_INTERVAL_SELECTION
1988 * MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
1989 */
1990 public void setSelectionMode(int selectionMode) {
1991 clearSelection();
1992 getSelectionModel().setSelectionMode(selectionMode);
1993 getColumnModel().getSelectionModel().setSelectionMode(selectionMode);
1994 }
1995
1996 /**
1997 * Sets whether the rows in this model can be selected.
1998 *
1999 * @param rowSelectionAllowed true if this model will allow row selection
2000 * @see #getRowSelectionAllowed
2001 * @beaninfo
2002 * bound: true
2003 * attribute: visualUpdate true
2004 * description: If true, an entire row is selected for each selected cell.
2005 */
2006 public void setRowSelectionAllowed(boolean rowSelectionAllowed) {
2007 boolean old = this.rowSelectionAllowed;
2008 this.rowSelectionAllowed = rowSelectionAllowed;
2009 if (old != rowSelectionAllowed) {
2010 repaint();
2011 }
2012 firePropertyChange("rowSelectionAllowed", old, rowSelectionAllowed);
2013 }
2014
2015 /**
2016 * Returns true if rows can be selected.
2017 *
2018 * @return true if rows can be selected, otherwise false
2019 * @see #setRowSelectionAllowed
2020 */
2021 public boolean getRowSelectionAllowed() {
2022 return rowSelectionAllowed;
2023 }
2024
2025 /**
2026 * Sets whether the columns in this model can be selected.
2027 *
2028 * @param columnSelectionAllowed true if this model will allow column selection
2029 * @see #getColumnSelectionAllowed
2030 * @beaninfo
2031 * bound: true
2032 * attribute: visualUpdate true
2033 * description: If true, an entire column is selected for each selected cell.
2034 */
2035 public void setColumnSelectionAllowed(boolean columnSelectionAllowed) {
2036 boolean old = columnModel.getColumnSelectionAllowed();
2037 columnModel.setColumnSelectionAllowed(columnSelectionAllowed);
2038 if (old != columnSelectionAllowed) {
2039 repaint();
2040 }
2041 firePropertyChange("columnSelectionAllowed", old, columnSelectionAllowed);
2042 }
2043
2044 /**
2045 * Returns true if columns can be selected.
2046 *
2047 * @return true if columns can be selected, otherwise false
2048 * @see #setColumnSelectionAllowed
2049 */
2050 public boolean getColumnSelectionAllowed() {
2051 return columnModel.getColumnSelectionAllowed();
2052 }
2053
2054 /**
2055 * Sets whether this table allows both a column selection and a
2056 * row selection to exist simultaneously. When set,
2057 * the table treats the intersection of the row and column selection
2058 * models as the selected cells. Override <code>isCellSelected</code> to
2059 * change this default behavior. This method is equivalent to setting
2060 * both the <code>rowSelectionAllowed</code> property and
2061 * <code>columnSelectionAllowed</code> property of the
2062 * <code>columnModel</code> to the supplied value.
2063 *
2064 * @param cellSelectionEnabled true if simultaneous row and column
2065 * selection is allowed
2066 * @see #getCellSelectionEnabled
2067 * @see #isCellSelected
2068 * @beaninfo
2069 * bound: true
2070 * attribute: visualUpdate true
2071 * description: Select a rectangular region of cells rather than
2072 * rows or columns.
2073 */
2074 public void setCellSelectionEnabled(boolean cellSelectionEnabled) {
2075 setRowSelectionAllowed(cellSelectionEnabled);
2076 setColumnSelectionAllowed(cellSelectionEnabled);
2077 boolean old = this.cellSelectionEnabled;
2078 this.cellSelectionEnabled = cellSelectionEnabled;
2079 firePropertyChange("cellSelectionEnabled", old, cellSelectionEnabled);
2080 }
2081
2082 /**
2083 * Returns true if both row and column selection models are enabled.
2084 * Equivalent to <code>getRowSelectionAllowed() &&
2085 * getColumnSelectionAllowed()</code>.
2086 *
2087 * @return true if both row and column selection models are enabled
2088 *
2089 * @see #setCellSelectionEnabled
2090 */
2091 public boolean getCellSelectionEnabled() {
2092 return getRowSelectionAllowed() && getColumnSelectionAllowed();
2093 }
2241 selectionModel.removeSelectionInterval(boundRow(index0), boundRow(index1));
2242 }
2243
2244 /**
2245 * Deselects the columns from <code>index0</code> to <code>index1</code>, inclusive.
2246 *
2247 * @exception IllegalArgumentException if <code>index0</code> or
2248 * <code>index1</code> lie outside
2249 * [0, <code>getColumnCount()</code>-1]
2250 * @param index0 one end of the interval
2251 * @param index1 the other end of the interval
2252 */
2253 public void removeColumnSelectionInterval(int index0, int index1) {
2254 columnModel.getSelectionModel().removeSelectionInterval(boundColumn(index0), boundColumn(index1));
2255 }
2256
2257 /**
2258 * Returns the index of the first selected row, -1 if no row is selected.
2259 * @return the index of the first selected row
2260 */
2261 public int getSelectedRow() {
2262 return selectionModel.getMinSelectionIndex();
2263 }
2264
2265 /**
2266 * Returns the index of the first selected column,
2267 * -1 if no column is selected.
2268 * @return the index of the first selected column
2269 */
2270 public int getSelectedColumn() {
2271 return columnModel.getSelectionModel().getMinSelectionIndex();
2272 }
2273
2274 /**
2275 * Returns the indices of all selected rows.
2276 *
2277 * @return an array of integers containing the indices of all selected rows,
2278 * or an empty array if no row is selected
2279 * @see #getSelectedRow
2280 */
2281 public int[] getSelectedRows() {
2282 int iMin = selectionModel.getMinSelectionIndex();
2283 int iMax = selectionModel.getMaxSelectionIndex();
2284
2285 if ((iMin == -1) || (iMax == -1)) {
2286 return new int[0];
2287 }
2288
2289 int[] rvTmp = new int[1+ (iMax - iMin)];
2290 int n = 0;
2291 for(int i = iMin; i <= iMax; i++) {
2292 if (selectionModel.isSelectedIndex(i)) {
2293 rvTmp[n++] = i;
2294 }
2295 }
2296 int[] rv = new int[n];
2297 System.arraycopy(rvTmp, 0, rv, 0, n);
2298 return rv;
2299 }
2300
2301 /**
2302 * Returns the indices of all selected columns.
2303 *
2304 * @return an array of integers containing the indices of all selected columns,
2305 * or an empty array if no column is selected
2306 * @see #getSelectedColumn
2307 */
2308 public int[] getSelectedColumns() {
2309 return columnModel.getSelectedColumns();
2310 }
2311
2312 /**
2313 * Returns the number of selected rows.
2314 *
2315 * @return the number of selected rows, 0 if no rows are selected
2316 */
2317 public int getSelectedRowCount() {
2318 int iMin = selectionModel.getMinSelectionIndex();
2319 int iMax = selectionModel.getMaxSelectionIndex();
2320 int count = 0;
2321
2322 for(int i = iMin; i <= iMax; i++) {
2323 if (selectionModel.isSelectedIndex(i)) {
2324 count++;
2325 }
2326 }
2327 return count;
2328 }
2329
2330 /**
2331 * Returns the number of selected columns.
2332 *
2333 * @return the number of selected columns, 0 if no columns are selected
2334 */
2335 public int getSelectedColumnCount() {
2336 return columnModel.getSelectedColumnCount();
2337 }
2338
2339 /**
2340 * Returns true if the specified index is in the valid range of rows,
2341 * and the row at that index is selected.
2342 *
2343 * @param row a row in the row model
2344 * @return true if <code>row</code> is a valid index and the row at
2345 * that index is selected (where 0 is the first row)
2346 */
2347 public boolean isRowSelected(int row) {
2348 return selectionModel.isSelectedIndex(row);
2349 }
2350
2351 /**
2352 * Returns true if the specified index is in the valid range of columns,
2353 * and the column at that index is selected.
2354 *
2502 return selectionForeground;
2503 }
2504
2505 /**
2506 * Sets the foreground color for selected cells. Cell renderers
2507 * can use this color to render text and graphics for selected
2508 * cells.
2509 * <p>
2510 * The default value of this property is defined by the look
2511 * and feel implementation.
2512 * <p>
2513 * This is a <a href="http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html">JavaBeans</a> bound property.
2514 *
2515 * @param selectionForeground the <code>Color</code> to use in the foreground
2516 * for selected list items
2517 * @see #getSelectionForeground
2518 * @see #setSelectionBackground
2519 * @see #setForeground
2520 * @see #setBackground
2521 * @see #setFont
2522 * @beaninfo
2523 * bound: true
2524 * description: A default foreground color for selected cells.
2525 */
2526 public void setSelectionForeground(Color selectionForeground) {
2527 Color old = this.selectionForeground;
2528 this.selectionForeground = selectionForeground;
2529 firePropertyChange("selectionForeground", old, selectionForeground);
2530 repaint();
2531 }
2532
2533 /**
2534 * Returns the background color for selected cells.
2535 *
2536 * @return the <code>Color</code> used for the background of selected list items
2537 * @see #setSelectionBackground
2538 * @see #setSelectionForeground
2539 */
2540 public Color getSelectionBackground() {
2541 return selectionBackground;
2542 }
2543
2544 /**
2545 * Sets the background color for selected cells. Cell renderers
2546 * can use this color to the fill selected cells.
2547 * <p>
2548 * The default value of this property is defined by the look
2549 * and feel implementation.
2550 * <p>
2551 * This is a <a href="http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html">JavaBeans</a> bound property.
2552 *
2553 * @param selectionBackground the <code>Color</code> to use for the background
2554 * of selected cells
2555 * @see #getSelectionBackground
2556 * @see #setSelectionForeground
2557 * @see #setForeground
2558 * @see #setBackground
2559 * @see #setFont
2560 * @beaninfo
2561 * bound: true
2562 * description: A default background color for selected cells.
2563 */
2564 public void setSelectionBackground(Color selectionBackground) {
2565 Color old = this.selectionBackground;
2566 this.selectionBackground = selectionBackground;
2567 firePropertyChange("selectionBackground", old, selectionBackground);
2568 repaint();
2569 }
2570
2571 /**
2572 * Returns the <code>TableColumn</code> object for the column in the table
2573 * whose identifier is equal to <code>identifier</code>, when compared using
2574 * <code>equals</code>.
2575 *
2576 * @return the <code>TableColumn</code> object that matches the identifier
2577 * @exception IllegalArgumentException if <code>identifier</code> is <code>null</code> or no <code>TableColumn</code> has this identifier
2578 *
2579 * @param identifier the identifier object
2580 */
2581 public TableColumn getColumn(Object identifier) {
2582 TableColumnModel cm = getColumnModel();
2583 int columnIndex = cm.getColumnIndex(identifier);
2659 * @since 1.6
2660 */
2661 public int convertRowIndexToModel(int viewRowIndex) {
2662 RowSorter<?> sorter = getRowSorter();
2663 if (sorter != null) {
2664 return sorter.convertRowIndexToModel(viewRowIndex);
2665 }
2666 return viewRowIndex;
2667 }
2668
2669 /**
2670 * Returns the number of rows that can be shown in the
2671 * <code>JTable</code>, given unlimited space. If a
2672 * <code>RowSorter</code> with a filter has been specified, the
2673 * number of rows returned may differ from that of the underlying
2674 * <code>TableModel</code>.
2675 *
2676 * @return the number of rows shown in the <code>JTable</code>
2677 * @see #getColumnCount
2678 */
2679 public int getRowCount() {
2680 RowSorter<?> sorter = getRowSorter();
2681 if (sorter != null) {
2682 return sorter.getViewRowCount();
2683 }
2684 return getModel().getRowCount();
2685 }
2686
2687 /**
2688 * Returns the number of columns in the column model. Note that this may
2689 * be different from the number of columns in the table model.
2690 *
2691 * @return the number of columns in the table
2692 * @see #getRowCount
2693 * @see #removeColumn
2694 */
2695 public int getColumnCount() {
2696 return getColumnModel().getColumnCount();
2697 }
2698
2699 /**
2700 * Returns the name of the column appearing in the view at
2701 * column position <code>column</code>.
2702 *
2703 * @param column the column in the view being queried
2704 * @return the name of the column at position <code>column</code>
2705 in the view where the first column is column 0
2706 */
2707 public String getColumnName(int column) {
2708 return getModel().getColumnName(convertColumnIndexToModel(column));
2709 }
2710
2711 /**
2712 * Returns the type of the column appearing in the view at
2713 * column position <code>column</code>.
2714 *
3543 editorComp.validate();
3544 editorComp.repaint();
3545
3546 setCellEditor(editor);
3547 setEditingRow(row);
3548 setEditingColumn(column);
3549 editor.addCellEditorListener(this);
3550
3551 return true;
3552 }
3553 return false;
3554 }
3555
3556 /**
3557 * Returns true if a cell is being edited.
3558 *
3559 * @return true if the table is editing a cell
3560 * @see #editingColumn
3561 * @see #editingRow
3562 */
3563 public boolean isEditing() {
3564 return cellEditor != null;
3565 }
3566
3567 /**
3568 * Returns the component that is handling the editing session.
3569 * If nothing is being edited, returns null.
3570 *
3571 * @return Component handling editing session
3572 */
3573 public Component getEditorComponent() {
3574 return editorComp;
3575 }
3576
3577 /**
3578 * Returns the index of the column that contains the cell currently
3579 * being edited. If nothing is being edited, returns -1.
3580 *
3581 * @return the index of the column that contains the cell currently
3582 * being edited; returns -1 if nothing being edited
3583 * @see #editingRow
3584 */
3585 public int getEditingColumn() {
3586 return editingColumn;
3587 }
3588
3589 /**
3590 * Returns the index of the row that contains the cell currently
3591 * being edited. If nothing is being edited, returns -1.
3592 *
3599 }
3600
3601 //
3602 // Managing TableUI
3603 //
3604
3605 /**
3606 * Returns the L&F object that renders this component.
3607 *
3608 * @return the <code>TableUI</code> object that renders this component
3609 */
3610 public TableUI getUI() {
3611 return (TableUI)ui;
3612 }
3613
3614 /**
3615 * Sets the L&F object that renders this component and repaints.
3616 *
3617 * @param ui the TableUI L&F object
3618 * @see UIDefaults#getUI
3619 * @beaninfo
3620 * bound: true
3621 * hidden: true
3622 * attribute: visualUpdate true
3623 * description: The UI object that implements the Component's LookAndFeel.
3624 */
3625 public void setUI(TableUI ui) {
3626 if (this.ui != ui) {
3627 super.setUI(ui);
3628 repaint();
3629 }
3630 }
3631
3632 /**
3633 * Notification from the <code>UIManager</code> that the L&F has changed.
3634 * Replaces the current UI object with the latest version from the
3635 * <code>UIManager</code>.
3636 *
3637 * @see JComponent#updateUI
3638 */
3639 public void updateUI() {
3640 // Update the UIs of the cell renderers, cell editors and header renderers.
3641 TableColumnModel cm = getColumnModel();
3642 for(int column = 0; column < cm.getColumnCount(); column++) {
3643 TableColumn aColumn = cm.getColumn(column);
3644 SwingUtilities.updateRendererOrEditorUI(aColumn.getCellRenderer());
3660
3661 // Update the UI of the table header
3662 if (tableHeader != null && tableHeader.getParent() == null) {
3663 tableHeader.updateUI();
3664 }
3665
3666 // Update UI applied to parent ScrollPane
3667 configureEnclosingScrollPaneUI();
3668
3669 setUI((TableUI)UIManager.getUI(this));
3670 }
3671
3672 /**
3673 * Returns the suffix used to construct the name of the L&F class used to
3674 * render this component.
3675 *
3676 * @return the string "TableUI"
3677 * @see JComponent#getUIClassID
3678 * @see UIDefaults#getUI
3679 */
3680 public String getUIClassID() {
3681 return uiClassID;
3682 }
3683
3684
3685 //
3686 // Managing models
3687 //
3688
3689 /**
3690 * Sets the data model for this table to <code>newModel</code> and registers
3691 * with it for listener notifications from the new data model.
3692 *
3693 * @param dataModel the new data source for this table
3694 * @exception IllegalArgumentException if <code>newModel</code> is <code>null</code>
3695 * @see #getModel
3696 * @beaninfo
3697 * bound: true
3698 * description: The model that is the source of the data for this view.
3699 */
3700 public void setModel(TableModel dataModel) {
3701 if (dataModel == null) {
3702 throw new IllegalArgumentException("Cannot set a null TableModel");
3703 }
3704 if (this.dataModel != dataModel) {
3705 TableModel old = this.dataModel;
3706 if (old != null) {
3707 old.removeTableModelListener(this);
3708 }
3709 this.dataModel = dataModel;
3710 dataModel.addTableModelListener(this);
3711
3712 tableChanged(new TableModelEvent(dataModel, TableModelEvent.HEADER_ROW));
3713
3714 firePropertyChange("model", old, dataModel);
3715
3716 if (getAutoCreateRowSorter()) {
3717 setRowSorter(new TableRowSorter<TableModel>(dataModel));
3718 }
3719 }
3721
3722 /**
3723 * Returns the <code>TableModel</code> that provides the data displayed by this
3724 * <code>JTable</code>.
3725 *
3726 * @return the <code>TableModel</code> that provides the data displayed by this <code>JTable</code>
3727 * @see #setModel
3728 */
3729 public TableModel getModel() {
3730 return dataModel;
3731 }
3732
3733 /**
3734 * Sets the column model for this table to <code>newModel</code> and registers
3735 * for listener notifications from the new column model. Also sets
3736 * the column model of the <code>JTableHeader</code> to <code>columnModel</code>.
3737 *
3738 * @param columnModel the new data source for this table
3739 * @exception IllegalArgumentException if <code>columnModel</code> is <code>null</code>
3740 * @see #getColumnModel
3741 * @beaninfo
3742 * bound: true
3743 * description: The object governing the way columns appear in the view.
3744 */
3745 public void setColumnModel(TableColumnModel columnModel) {
3746 if (columnModel == null) {
3747 throw new IllegalArgumentException("Cannot set a null ColumnModel");
3748 }
3749 TableColumnModel old = this.columnModel;
3750 if (columnModel != old) {
3751 if (old != null) {
3752 old.removeColumnModelListener(this);
3753 }
3754 this.columnModel = columnModel;
3755 columnModel.addColumnModelListener(this);
3756
3757 // Set the column model of the header as well.
3758 if (tableHeader != null) {
3759 tableHeader.setColumnModel(columnModel);
3760 }
3761
3762 firePropertyChange("columnModel", old, columnModel);
3763 resizeAndRepaint();
3764 }
3765 }
3766
3767 /**
3768 * Returns the <code>TableColumnModel</code> that contains all column information
3769 * of this table.
3770 *
3771 * @return the object that provides the column state of the table
3772 * @see #setColumnModel
3773 */
3774 public TableColumnModel getColumnModel() {
3775 return columnModel;
3776 }
3777
3778 /**
3779 * Sets the row selection model for this table to <code>newModel</code>
3780 * and registers for listener notifications from the new selection model.
3781 *
3782 * @param newModel the new selection model
3783 * @exception IllegalArgumentException if <code>newModel</code> is <code>null</code>
3784 * @see #getSelectionModel
3785 * @beaninfo
3786 * bound: true
3787 * description: The selection model for rows.
3788 */
3789 public void setSelectionModel(ListSelectionModel newModel) {
3790 if (newModel == null) {
3791 throw new IllegalArgumentException("Cannot set a null SelectionModel");
3792 }
3793
3794 ListSelectionModel oldModel = selectionModel;
3795
3796 if (newModel != oldModel) {
3797 if (oldModel != null) {
3798 oldModel.removeListSelectionListener(this);
3799 }
3800
3801 selectionModel = newModel;
3802 newModel.addListSelectionListener(this);
3803
3804 firePropertyChange("selectionModel", oldModel, newModel);
3805 repaint();
3806 }
3807 }
3808
4756 * Application code will not use these methods explicitly, they
4757 * are used internally by JTable.
4758 *
4759 * @param e the event received
4760 * @see CellEditorListener
4761 */
4762 public void editingCanceled(ChangeEvent e) {
4763 removeEditor();
4764 }
4765
4766 //
4767 // Implementing the Scrollable interface
4768 //
4769
4770 /**
4771 * Sets the preferred size of the viewport for this table.
4772 *
4773 * @param size a <code>Dimension</code> object specifying the <code>preferredSize</code> of a
4774 * <code>JViewport</code> whose view is this table
4775 * @see Scrollable#getPreferredScrollableViewportSize
4776 * @beaninfo
4777 * description: The preferred size of the viewport.
4778 */
4779 public void setPreferredScrollableViewportSize(Dimension size) {
4780 preferredViewportSize = size;
4781 }
4782
4783 /**
4784 * Returns the preferred size of the viewport for this table.
4785 *
4786 * @return a <code>Dimension</code> object containing the <code>preferredSize</code> of the <code>JViewport</code>
4787 * which displays this table
4788 * @see Scrollable#getPreferredScrollableViewportSize
4789 */
4790 public Dimension getPreferredScrollableViewportSize() {
4791 return preferredViewportSize;
4792 }
4793
4794 /**
4795 * Returns the scroll increment (in pixels) that completely exposes one new
4796 * row or column (depending on the orientation).
4797 * <p>
4798 * This method is called each time the user requests a unit scroll.
5194 return rect.y + rect.height;
5195 }
5196 else if (getComponentOrientation().isLeftToRight()) {
5197 return rect.x + rect.width;
5198 }
5199 else { // Horizontal, right-to-left
5200 return rect.x;
5201 }
5202 }
5203
5204 /**
5205 * Returns false if <code>autoResizeMode</code> is set to
5206 * <code>AUTO_RESIZE_OFF</code>, which indicates that the
5207 * width of the viewport does not determine the width
5208 * of the table. Otherwise returns true.
5209 *
5210 * @return false if <code>autoResizeMode</code> is set
5211 * to <code>AUTO_RESIZE_OFF</code>, otherwise returns true
5212 * @see Scrollable#getScrollableTracksViewportWidth
5213 */
5214 public boolean getScrollableTracksViewportWidth() {
5215 return !(autoResizeMode == AUTO_RESIZE_OFF);
5216 }
5217
5218 /**
5219 * Returns {@code false} to indicate that the height of the viewport does
5220 * not determine the height of the table, unless
5221 * {@code getFillsViewportHeight} is {@code true} and the preferred height
5222 * of the table is smaller than the viewport's height.
5223 *
5224 * @return {@code false} unless {@code getFillsViewportHeight} is
5225 * {@code true} and the table needs to be stretched to fill
5226 * the viewport
5227 * @see Scrollable#getScrollableTracksViewportHeight
5228 * @see #setFillsViewportHeight
5229 * @see #getFillsViewportHeight
5230 */
5231 public boolean getScrollableTracksViewportHeight() {
5232 Container parent = SwingUtilities.getUnwrappedParent(this);
5233 return getFillsViewportHeight()
5234 && parent instanceof JViewport
5235 && parent.getHeight() > getPreferredSize().height;
5236 }
5237
5238 /**
5239 * Sets whether or not this table is always made large enough
5240 * to fill the height of an enclosing viewport. If the preferred
5241 * height of the table is smaller than the viewport, then the table
5242 * will be stretched to fill the viewport. In other words, this
5243 * ensures the table is never smaller than the viewport.
5244 * The default for this property is {@code false}.
5245 *
5246 * @param fillsViewportHeight whether or not this table is always
5247 * made large enough to fill the height of an enclosing
5248 * viewport
5249 * @see #getFillsViewportHeight
5250 * @see #getScrollableTracksViewportHeight
5251 * @since 1.6
5252 * @beaninfo
5253 * bound: true
5254 * description: Whether or not this table is always made large enough
5255 * to fill the height of an enclosing viewport
5256 */
5257 public void setFillsViewportHeight(boolean fillsViewportHeight) {
5258 boolean old = this.fillsViewportHeight;
5259 this.fillsViewportHeight = fillsViewportHeight;
5260 resizeAndRepaint();
5261 firePropertyChange("fillsViewportHeight", old, fillsViewportHeight);
5262 }
5263
5264 /**
5265 * Returns whether or not this table is always made large enough
5266 * to fill the height of an enclosing viewport.
5267 *
5268 * @return whether or not this table is always made large enough
5269 * to fill the height of an enclosing viewport
5270 * @see #setFillsViewportHeight
5271 * @since 1.6
5272 */
5273 public boolean getFillsViewportHeight() {
5274 return fillsViewportHeight;
5275 }
5276
5633 }
5634
5635 /**
5636 * Returns the active cell editor, which is {@code null} if the table
5637 * is not currently editing.
5638 *
5639 * @return the {@code TableCellEditor} that does the editing,
5640 * or {@code null} if the table is not currently editing.
5641 * @see #cellEditor
5642 * @see #getCellEditor(int, int)
5643 */
5644 public TableCellEditor getCellEditor() {
5645 return cellEditor;
5646 }
5647
5648 /**
5649 * Sets the active cell editor.
5650 *
5651 * @param anEditor the active cell editor
5652 * @see #cellEditor
5653 * @beaninfo
5654 * bound: true
5655 * description: The table's active cell editor.
5656 */
5657 public void setCellEditor(TableCellEditor anEditor) {
5658 TableCellEditor oldEditor = cellEditor;
5659 cellEditor = anEditor;
5660 firePropertyChange("tableCellEditor", oldEditor, anEditor);
5661 }
5662
5663 /**
5664 * Sets the <code>editingColumn</code> variable.
5665 * @param aColumn the column of the cell to be edited
5666 *
5667 * @see #editingColumn
5668 */
5669 public void setEditingColumn(int aColumn) {
5670 editingColumn = aColumn;
5671 }
5672
5673 /**
5674 * Sets the <code>editingRow</code> variable.
5675 * @param aRow the row of the cell to be edited
5676 *
6629 }
6630
6631 return retVal;
6632 }
6633 }
6634 }
6635
6636 /////////////////
6637 // Accessibility support
6638 ////////////////
6639
6640 /**
6641 * Gets the AccessibleContext associated with this JTable.
6642 * For tables, the AccessibleContext takes the form of an
6643 * AccessibleJTable.
6644 * A new AccessibleJTable instance is created if necessary.
6645 *
6646 * @return an AccessibleJTable that serves as the
6647 * AccessibleContext of this JTable
6648 */
6649 public AccessibleContext getAccessibleContext() {
6650 if (accessibleContext == null) {
6651 accessibleContext = new AccessibleJTable();
6652 }
6653 return accessibleContext;
6654 }
6655
6656 //
6657 // *** should also implement AccessibleSelection?
6658 // *** and what's up with keyboard navigation/manipulation?
6659 //
6660 /**
6661 * This class implements accessibility support for the
6662 * <code>JTable</code> class. It provides an implementation of the
6663 * Java Accessibility API appropriate to table user-interface elements.
6664 * <p>
6665 * <strong>Warning:</strong>
6666 * Serialized objects of this class will not be compatible with
6667 * future Swing releases. The current serialization support is
6668 * appropriate for short term storage or RMI between applications running
|
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package javax.swing;
26
27 import java.util.*;
28
29 import java.applet.Applet;
30 import java.awt.*;
31 import java.awt.event.*;
32 import java.awt.print.*;
33
34 import java.beans.JavaBean;
35 import java.beans.BeanProperty;
36 import java.beans.PropertyChangeEvent;
37 import java.beans.PropertyChangeListener;
38
39 import java.io.ObjectOutputStream;
40 import java.io.ObjectInputStream;
41 import java.io.IOException;
42 import java.io.InvalidObjectException;
43
44 import javax.accessibility.*;
45
46 import javax.swing.event.*;
47 import javax.swing.plaf.*;
48 import javax.swing.table.*;
49 import javax.swing.border.*;
50
51 import java.text.NumberFormat;
52 import java.text.DateFormat;
53 import java.text.MessageFormat;
54
55 import javax.print.attribute.*;
56 import javax.print.PrintService;
57
58 import sun.reflect.misc.ReflectUtil;
59
60 import sun.swing.SwingUtilities2;
61 import sun.swing.SwingUtilities2.Section;
62 import static sun.swing.SwingUtilities2.Section.*;
63 import sun.swing.PrintingStatus;
64
65 /**
66 * The <code>JTable</code> is used to display and edit regular two-dimensional tables
67 * of cells.
68 * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/table.html">How to Use Tables</a>
69 * in <em>The Java Tutorial</em>
70 * for task-oriented documentation and examples of using <code>JTable</code>.
71 *
72 * <p>
73 * The <code>JTable</code> has many
74 * facilities that make it possible to customize its rendering and editing
75 * but provides defaults for these features so that simple tables can be
76 * set up easily. For example, to set up a table with 10 rows and 10
77 * columns of numbers:
190 * <p>
191 * As for all <code>JComponent</code> classes, you can use
192 * {@link InputMap} and {@link ActionMap} to associate an
193 * {@link Action} object with a {@link KeyStroke} and execute the
194 * action under specified conditions.
195 * <p>
196 * <strong>Warning:</strong> Swing is not thread safe. For more
197 * information see <a
198 * href="package-summary.html#threading">Swing's Threading
199 * Policy</a>.
200 * <p>
201 * <strong>Warning:</strong>
202 * Serialized objects of this class will not be compatible with
203 * future Swing releases. The current serialization support is
204 * appropriate for short term storage or RMI between applications running
205 * the same version of Swing. As of 1.4, support for long term storage
206 * of all JavaBeans™
207 * has been added to the <code>java.beans</code> package.
208 * Please see {@link java.beans.XMLEncoder}.
209 *
210 * @author Philip Milne
211 * @author Shannon Hickey (printing support)
212 * @see javax.swing.table.DefaultTableModel
213 * @see javax.swing.table.TableRowSorter
214 * @since 1.2
215 */
216 /* The first versions of the JTable, contained in Swing-0.1 through
217 * Swing-0.4, were written by Alan Chung.
218 */
219 @JavaBean(defaultProperty = "UI", description = "A component which displays data in a two dimensional grid.")
220 @SwingContainer(false)
221 @SuppressWarnings("serial") // Same-version serialization only
222 public class JTable extends JComponent implements TableModelListener, Scrollable,
223 TableColumnModelListener, ListSelectionListener, CellEditorListener,
224 Accessible, RowSorterListener
225 {
226 //
227 // Static Constants
228 //
229
230 /**
231 * @see #getUIClassID
232 * @see #readObject
233 */
234 private static final String uiClassID = "TableUI";
235
236 /** Do not adjust column widths automatically; use a horizontal scrollbar instead. */
237 public static final int AUTO_RESIZE_OFF = 0;
238
239 /** When a column is adjusted in the UI, adjust the next column the opposite way. */
240 public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
873 * @param aTable a {@code JTable} to be used for the scroll pane
874 * @return a {@code JScrollPane} created using {@code aTable}
875 * @deprecated As of Swing version 1.0.2,
876 * replaced by <code>new JScrollPane(aTable)</code>.
877 */
878 @Deprecated
879 static public JScrollPane createScrollPaneForTable(JTable aTable) {
880 return new JScrollPane(aTable);
881 }
882
883 //
884 // Table Attributes
885 //
886
887 /**
888 * Sets the <code>tableHeader</code> working with this <code>JTable</code> to <code>newHeader</code>.
889 * It is legal to have a <code>null</code> <code>tableHeader</code>.
890 *
891 * @param tableHeader new tableHeader
892 * @see #getTableHeader
893 */
894 @BeanProperty(description
895 = "The JTableHeader instance which renders the column headers.")
896 public void setTableHeader(JTableHeader tableHeader) {
897 if (this.tableHeader != tableHeader) {
898 JTableHeader old = this.tableHeader;
899 // Release the old header
900 if (old != null) {
901 old.setTable(null);
902 }
903 this.tableHeader = tableHeader;
904 if (tableHeader != null) {
905 tableHeader.setTable(this);
906 }
907 firePropertyChange("tableHeader", old, tableHeader);
908 }
909 }
910
911 /**
912 * Returns the <code>tableHeader</code> used by this <code>JTable</code>.
913 *
914 * @return the <code>tableHeader</code> used by this table
915 * @see #setTableHeader
916 */
917 public JTableHeader getTableHeader() {
918 return tableHeader;
919 }
920
921 /**
922 * Sets the height, in pixels, of all cells to <code>rowHeight</code>,
923 * revalidates, and repaints.
924 * The height of the cells will be equal to the row height minus
925 * the row margin.
926 *
927 * @param rowHeight new row height
928 * @exception IllegalArgumentException if <code>rowHeight</code> is
929 * less than 1
930 * @see #getRowHeight
931 */
932 @BeanProperty(description
933 = "The height of the specified row.")
934 public void setRowHeight(int rowHeight) {
935 if (rowHeight <= 0) {
936 throw new IllegalArgumentException("New row height less than 1");
937 }
938 int old = this.rowHeight;
939 this.rowHeight = rowHeight;
940 rowModel = null;
941 if (sortManager != null) {
942 sortManager.modelRowSizes = null;
943 }
944 isRowHeightSet = true;
945 resizeAndRepaint();
946 firePropertyChange("rowHeight", old, rowHeight);
947 }
948
949 /**
950 * Returns the height of a table row, in pixels.
951 *
952 * @return the height in pixels of a table row
953 * @see #setRowHeight
956 return rowHeight;
957 }
958
959 private SizeSequence getRowModel() {
960 if (rowModel == null) {
961 rowModel = new SizeSequence(getRowCount(), getRowHeight());
962 }
963 return rowModel;
964 }
965
966 /**
967 * Sets the height for <code>row</code> to <code>rowHeight</code>,
968 * revalidates, and repaints. The height of the cells in this row
969 * will be equal to the row height minus the row margin.
970 *
971 * @param row the row whose height is being
972 changed
973 * @param rowHeight new row height, in pixels
974 * @exception IllegalArgumentException if <code>rowHeight</code> is
975 * less than 1
976 * @since 1.3
977 */
978 @BeanProperty(description
979 = "The height in pixels of the cells in <code>row</code>")
980 public void setRowHeight(int row, int rowHeight) {
981 if (rowHeight <= 0) {
982 throw new IllegalArgumentException("New row height less than 1");
983 }
984 getRowModel().setSize(row, rowHeight);
985 if (sortManager != null) {
986 sortManager.setViewRowHeight(row, rowHeight);
987 }
988 resizeAndRepaint();
989 }
990
991 /**
992 * Returns the height, in pixels, of the cells in <code>row</code>.
993 * @param row the row whose height is to be returned
994 * @return the height, in pixels, of the cells in the row
995 * @since 1.3
996 */
997 public int getRowHeight(int row) {
998 return (rowModel == null) ? getRowHeight() : rowModel.getSize(row);
999 }
1000
1001 /**
1002 * Sets the amount of empty space between cells in adjacent rows.
1003 *
1004 * @param rowMargin the number of pixels between cells in a row
1005 * @see #getRowMargin
1006 */
1007 @BeanProperty(description
1008 = "The amount of space between cells.")
1009 public void setRowMargin(int rowMargin) {
1010 int old = this.rowMargin;
1011 this.rowMargin = rowMargin;
1012 resizeAndRepaint();
1013 firePropertyChange("rowMargin", old, rowMargin);
1014 }
1015
1016 /**
1017 * Gets the amount of empty space, in pixels, between cells. Equivalent to:
1018 * <code>getIntercellSpacing().height</code>.
1019 * @return the number of pixels between cells in a row
1020 *
1021 * @see #setRowMargin
1022 */
1023 public int getRowMargin() {
1024 return rowMargin;
1025 }
1026
1027 /**
1028 * Sets the <code>rowMargin</code> and the <code>columnMargin</code> --
1029 * the height and width of the space between cells -- to
1030 * <code>intercellSpacing</code>.
1031 *
1032 * @param intercellSpacing a <code>Dimension</code>
1033 * specifying the new width
1034 * and height between cells
1035 * @see #getIntercellSpacing
1036 */
1037 @BeanProperty(bound = false, description
1038 = "The spacing between the cells, drawn in the background color of the JTable.")
1039 public void setIntercellSpacing(Dimension intercellSpacing) {
1040 // Set the rowMargin here and columnMargin in the TableColumnModel
1041 setRowMargin(intercellSpacing.height);
1042 getColumnModel().setColumnMargin(intercellSpacing.width);
1043
1044 resizeAndRepaint();
1045 }
1046
1047 /**
1048 * Returns the horizontal and vertical space between cells.
1049 * The default spacing is look and feel dependent.
1050 *
1051 * @return the horizontal and vertical spacing between cells
1052 * @see #setIntercellSpacing
1053 */
1054 public Dimension getIntercellSpacing() {
1055 return new Dimension(getColumnModel().getColumnMargin(), rowMargin);
1056 }
1057
1058 /**
1059 * Sets the color used to draw grid lines to <code>gridColor</code> and redisplays.
1060 * The default color is look and feel dependent.
1061 *
1062 * @param gridColor the new color of the grid lines
1063 * @exception IllegalArgumentException if <code>gridColor</code> is <code>null</code>
1064 * @see #getGridColor
1065 */
1066 @BeanProperty(description
1067 = "The grid color.")
1068 public void setGridColor(Color gridColor) {
1069 if (gridColor == null) {
1070 throw new IllegalArgumentException("New color is null");
1071 }
1072 Color old = this.gridColor;
1073 this.gridColor = gridColor;
1074 firePropertyChange("gridColor", old, gridColor);
1075 // Redraw
1076 repaint();
1077 }
1078
1079 /**
1080 * Returns the color used to draw grid lines.
1081 * The default color is look and feel dependent.
1082 *
1083 * @return the color used to draw grid lines
1084 * @see #setGridColor
1085 */
1086 public Color getGridColor() {
1087 return gridColor;
1088 }
1089
1090 /**
1091 * Sets whether the table draws grid lines around cells.
1092 * If <code>showGrid</code> is true it does; if it is false it doesn't.
1093 * There is no <code>getShowGrid</code> method as this state is held
1094 * in two variables -- <code>showHorizontalLines</code> and <code>showVerticalLines</code> --
1095 * each of which can be queried independently.
1096 *
1097 * @param showGrid true if table view should draw grid lines
1098 *
1099 * @see #setShowVerticalLines
1100 * @see #setShowHorizontalLines
1101 */
1102 @BeanProperty(description
1103 = "The color used to draw the grid lines.")
1104 public void setShowGrid(boolean showGrid) {
1105 setShowHorizontalLines(showGrid);
1106 setShowVerticalLines(showGrid);
1107
1108 // Redraw
1109 repaint();
1110 }
1111
1112 /**
1113 * Sets whether the table draws horizontal lines between cells.
1114 * If <code>showHorizontalLines</code> is true it does; if it is false it doesn't.
1115 *
1116 * @param showHorizontalLines true if table view should draw horizontal lines
1117 * @see #getShowHorizontalLines
1118 * @see #setShowGrid
1119 * @see #setShowVerticalLines
1120 */
1121 @BeanProperty(description
1122 = "Whether horizontal lines should be drawn in between the cells.")
1123 public void setShowHorizontalLines(boolean showHorizontalLines) {
1124 boolean old = this.showHorizontalLines;
1125 this.showHorizontalLines = showHorizontalLines;
1126 firePropertyChange("showHorizontalLines", old, showHorizontalLines);
1127
1128 // Redraw
1129 repaint();
1130 }
1131
1132 /**
1133 * Sets whether the table draws vertical lines between cells.
1134 * If <code>showVerticalLines</code> is true it does; if it is false it doesn't.
1135 *
1136 * @param showVerticalLines true if table view should draw vertical lines
1137 * @see #getShowVerticalLines
1138 * @see #setShowGrid
1139 * @see #setShowHorizontalLines
1140 */
1141 @BeanProperty(description
1142 = "Whether vertical lines should be drawn in between the cells.")
1143 public void setShowVerticalLines(boolean showVerticalLines) {
1144 boolean old = this.showVerticalLines;
1145 this.showVerticalLines = showVerticalLines;
1146 firePropertyChange("showVerticalLines", old, showVerticalLines);
1147 // Redraw
1148 repaint();
1149 }
1150
1151 /**
1152 * Returns true if the table draws horizontal lines between cells, false if it
1153 * doesn't. The default value is look and feel dependent.
1154 *
1155 * @return true if the table draws horizontal lines between cells, false if it
1156 * doesn't
1157 * @see #setShowHorizontalLines
1158 */
1159 public boolean getShowHorizontalLines() {
1160 return showHorizontalLines;
1161 }
1162
1169 * @see #setShowVerticalLines
1170 */
1171 public boolean getShowVerticalLines() {
1172 return showVerticalLines;
1173 }
1174
1175 /**
1176 * Sets the table's auto resize mode when the table is resized. For further
1177 * information on how the different resize modes work, see
1178 * {@link #doLayout}.
1179 *
1180 * @param mode One of 5 legal values:
1181 * AUTO_RESIZE_OFF,
1182 * AUTO_RESIZE_NEXT_COLUMN,
1183 * AUTO_RESIZE_SUBSEQUENT_COLUMNS,
1184 * AUTO_RESIZE_LAST_COLUMN,
1185 * AUTO_RESIZE_ALL_COLUMNS
1186 *
1187 * @see #getAutoResizeMode
1188 * @see #doLayout
1189 */
1190 @BeanProperty(enumerationValues = {
1191 "JTable.AUTO_RESIZE_OFF",
1192 "JTable.AUTO_RESIZE_NEXT_COLUMN",
1193 "JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS",
1194 "JTable.AUTO_RESIZE_LAST_COLUMN",
1195 "JTable.AUTO_RESIZE_ALL_COLUMNS"}, description
1196 = "Whether the columns should adjust themselves automatically.")
1197 public void setAutoResizeMode(int mode) {
1198 if (isValidAutoResizeMode(mode)) {
1199 int old = autoResizeMode;
1200 autoResizeMode = mode;
1201 resizeAndRepaint();
1202 if (tableHeader != null) {
1203 tableHeader.resizeAndRepaint();
1204 }
1205 firePropertyChange("autoResizeMode", old, autoResizeMode);
1206 }
1207 }
1208
1209 private static boolean isValidAutoResizeMode(int mode) {
1210 return (mode == AUTO_RESIZE_OFF)
1211 || (mode == AUTO_RESIZE_NEXT_COLUMN)
1212 || (mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS)
1213 || (mode == AUTO_RESIZE_LAST_COLUMN)
1214 || (mode == AUTO_RESIZE_ALL_COLUMNS);
1215 }
1216
1218 * Returns the auto resize mode of the table. The default mode
1219 * is AUTO_RESIZE_SUBSEQUENT_COLUMNS.
1220 *
1221 * @return the autoResizeMode of the table
1222 *
1223 * @see #setAutoResizeMode
1224 * @see #doLayout
1225 */
1226 public int getAutoResizeMode() {
1227 return autoResizeMode;
1228 }
1229
1230 /**
1231 * Sets this table's <code>autoCreateColumnsFromModel</code> flag.
1232 * This method calls <code>createDefaultColumnsFromModel</code> if
1233 * <code>autoCreateColumnsFromModel</code> changes from false to true.
1234 *
1235 * @param autoCreateColumnsFromModel true if <code>JTable</code> should automatically create columns
1236 * @see #getAutoCreateColumnsFromModel
1237 * @see #createDefaultColumnsFromModel
1238 */
1239 @BeanProperty(description
1240 = "Automatically populates the columnModel when a new TableModel is submitted.")
1241 public void setAutoCreateColumnsFromModel(boolean autoCreateColumnsFromModel) {
1242 if (this.autoCreateColumnsFromModel != autoCreateColumnsFromModel) {
1243 boolean old = this.autoCreateColumnsFromModel;
1244 this.autoCreateColumnsFromModel = autoCreateColumnsFromModel;
1245 if (autoCreateColumnsFromModel) {
1246 createDefaultColumnsFromModel();
1247 }
1248 firePropertyChange("autoCreateColumnsFromModel", old, autoCreateColumnsFromModel);
1249 }
1250 }
1251
1252 /**
1253 * Determines whether the table will create default columns from the model.
1254 * If true, <code>setModel</code> will clear any existing columns and
1255 * create new columns from the new model. Also, if the event in
1256 * the <code>tableChanged</code> notification specifies that the
1257 * entire table changed, then the columns will be rebuilt.
1258 * The default is true.
1259 *
1260 * @return the autoCreateColumnsFromModel of the table
1411 * feels (including those that subclass {@code BasicLookAndFeel}) begin a
1412 * drag and drop operation whenever the user presses the mouse button over
1413 * an item (in single selection mode) or a selection (in other selection
1414 * modes) and then moves the mouse a few pixels. Setting this property to
1415 * {@code true} can therefore have a subtle effect on how selections behave.
1416 * <p>
1417 * If a look and feel is used that ignores this property, you can still
1418 * begin a drag and drop operation by calling {@code exportAsDrag} on the
1419 * table's {@code TransferHandler}.
1420 *
1421 * @param b whether or not to enable automatic drag handling
1422 * @exception HeadlessException if
1423 * <code>b</code> is <code>true</code> and
1424 * <code>GraphicsEnvironment.isHeadless()</code>
1425 * returns <code>true</code>
1426 * @see java.awt.GraphicsEnvironment#isHeadless
1427 * @see #getDragEnabled
1428 * @see #setTransferHandler
1429 * @see TransferHandler
1430 * @since 1.4
1431 */
1432 @BeanProperty(bound = false, description
1433 = "determines whether automatic drag handling is enabled")
1434 public void setDragEnabled(boolean b) {
1435 checkDragEnabled(b);
1436 dragEnabled = b;
1437 }
1438
1439 private void checkDragEnabled(boolean b) {
1440 if (b && GraphicsEnvironment.isHeadless()) {
1441 throw new HeadlessException();
1442 }
1443 }
1444
1445 /**
1446 * Returns whether or not automatic drag handling is enabled.
1447 *
1448 * @return the value of the {@code dragEnabled} property
1449 * @see #setDragEnabled
1450 * @since 1.4
1451 */
1452 public boolean getDragEnabled() {
1453 return dragEnabled;
1801 }
1802
1803 /**
1804 * Returns the location that this component should visually indicate
1805 * as the drop location during a DnD operation over the component,
1806 * or {@code null} if no location is to currently be shown.
1807 * <p>
1808 * This method is not meant for querying the drop location
1809 * from a {@code TransferHandler}, as the drop location is only
1810 * set after the {@code TransferHandler}'s <code>canImport</code>
1811 * has returned and has allowed for the location to be shown.
1812 * <p>
1813 * When this property changes, a property change event with
1814 * name "dropLocation" is fired by the component.
1815 *
1816 * @return the drop location
1817 * @see #setDropMode
1818 * @see TransferHandler#canImport(TransferHandler.TransferSupport)
1819 * @since 1.6
1820 */
1821 @BeanProperty(bound = false)
1822 public final DropLocation getDropLocation() {
1823 return dropLocation;
1824 }
1825
1826 /**
1827 * Specifies whether a {@code RowSorter} should be created for the
1828 * table whenever its model changes.
1829 * <p>
1830 * When {@code setAutoCreateRowSorter(true)} is invoked, a {@code
1831 * TableRowSorter} is immediately created and installed on the
1832 * table. While the {@code autoCreateRowSorter} property remains
1833 * {@code true}, every time the model is changed, a new {@code
1834 * TableRowSorter} is created and set as the table's row sorter.
1835 * The default value for the {@code autoCreateRowSorter}
1836 * property is {@code false}.
1837 *
1838 * @param autoCreateRowSorter whether or not a {@code RowSorter}
1839 * should be automatically created
1840 * @see javax.swing.table.TableRowSorter
1841 * @since 1.6
1842 */
1843 @BeanProperty(preferred = true, description
1844 = "Whether or not to turn on sorting by default.")
1845 public void setAutoCreateRowSorter(boolean autoCreateRowSorter) {
1846 boolean oldValue = this.autoCreateRowSorter;
1847 this.autoCreateRowSorter = autoCreateRowSorter;
1848 if (autoCreateRowSorter) {
1849 setRowSorter(new TableRowSorter<TableModel>(getModel()));
1850 }
1851 firePropertyChange("autoCreateRowSorter", oldValue,
1852 autoCreateRowSorter);
1853 }
1854
1855 /**
1856 * Returns {@code true} if whenever the model changes, a new
1857 * {@code RowSorter} should be created and installed
1858 * as the table's sorter; otherwise, returns {@code false}.
1859 *
1860 * @return true if a {@code RowSorter} should be created when
1861 * the model changes
1862 * @since 1.6
1863 */
1864 public boolean getAutoCreateRowSorter() {
1865 return autoCreateRowSorter;
1866 }
1867
1868 /**
1869 * Specifies whether the selection should be updated after sorting.
1870 * If true, on sorting the selection is reset such that
1871 * the same rows, in terms of the model, remain selected. The default
1872 * is true.
1873 *
1874 * @param update whether or not to update the selection on sorting
1875 * @since 1.6
1876 */
1877 @BeanProperty(expert = true, description
1878 = "Whether or not to update the selection on sorting")
1879 public void setUpdateSelectionOnSort(boolean update) {
1880 if (updateSelectionOnSort != update) {
1881 updateSelectionOnSort = update;
1882 firePropertyChange("updateSelectionOnSort", !update, update);
1883 }
1884 }
1885
1886 /**
1887 * Returns true if the selection should be updated after sorting.
1888 *
1889 * @return whether to update the selection on a sort
1890 * @since 1.6
1891 */
1892 public boolean getUpdateSelectionOnSort() {
1893 return updateSelectionOnSort;
1894 }
1895
1896 /**
1897 * Sets the <code>RowSorter</code>. <code>RowSorter</code> is used
1898 * to provide sorting and filtering to a <code>JTable</code>.
1899 * <p>
1900 * This method clears the selection and resets any variable row heights.
1901 * <p>
1902 * This method fires a <code>PropertyChangeEvent</code> when appropriate,
1903 * with the property name <code>"rowSorter"</code>. For
1904 * backward-compatibility, this method fires an additional event with the
1905 * property name <code>"sorter"</code>.
1906 * <p>
1907 * If the underlying model of the <code>RowSorter</code> differs from
1908 * that of this <code>JTable</code> undefined behavior will result.
1909 *
1910 * @param sorter the <code>RowSorter</code>; <code>null</code> turns
1911 * sorting off
1912 * @see javax.swing.table.TableRowSorter
1913 * @since 1.6
1914 */
1915 @BeanProperty(description
1916 = "The table's RowSorter")
1917 public void setRowSorter(RowSorter<? extends TableModel> sorter) {
1918 RowSorter<? extends TableModel> oldRowSorter = null;
1919 if (sortManager != null) {
1920 oldRowSorter = sortManager.sorter;
1921 sortManager.dispose();
1922 sortManager = null;
1923 }
1924 rowModel = null;
1925 clearSelectionAndLeadAnchor();
1926 if (sorter != null) {
1927 sortManager = new SortManager(sorter);
1928 }
1929 resizeAndRepaint();
1930 firePropertyChange("rowSorter", oldRowSorter, sorter);
1931 firePropertyChange("sorter", oldRowSorter, sorter);
1932 }
1933
1934 /**
1935 * Returns the object responsible for sorting.
1936 *
1948 * Sets the table's selection mode to allow only single selections, a single
1949 * contiguous interval, or multiple intervals.
1950 * <P>
1951 * <b>Note:</b>
1952 * <code>JTable</code> provides all the methods for handling
1953 * column and row selection. When setting states,
1954 * such as <code>setSelectionMode</code>, it not only
1955 * updates the mode for the row selection model but also sets similar
1956 * values in the selection model of the <code>columnModel</code>.
1957 * If you want to have the row and column selection models operating
1958 * in different modes, set them both directly.
1959 * <p>
1960 * Both the row and column selection models for <code>JTable</code>
1961 * default to using a <code>DefaultListSelectionModel</code>
1962 * so that <code>JTable</code> works the same way as the
1963 * <code>JList</code>. See the <code>setSelectionMode</code> method
1964 * in <code>JList</code> for details about the modes.
1965 *
1966 * @param selectionMode the mode used by the row and column selection models
1967 * @see JList#setSelectionMode
1968 */
1969 @BeanProperty(enumerationValues = {
1970 "ListSelectionModel.SINGLE_SELECTION",
1971 "ListSelectionModel.SINGLE_INTERVAL_SELECTION",
1972 "ListSelectionModel.MULTIPLE_INTERVAL_SELECTION"}, description
1973 = "The selection mode used by the row and column selection models.")
1974 public void setSelectionMode(int selectionMode) {
1975 clearSelection();
1976 getSelectionModel().setSelectionMode(selectionMode);
1977 getColumnModel().getSelectionModel().setSelectionMode(selectionMode);
1978 }
1979
1980 /**
1981 * Sets whether the rows in this model can be selected.
1982 *
1983 * @param rowSelectionAllowed true if this model will allow row selection
1984 * @see #getRowSelectionAllowed
1985 */
1986 @BeanProperty(visualUpdate = true, description
1987 = "If true, an entire row is selected for each selected cell.")
1988 public void setRowSelectionAllowed(boolean rowSelectionAllowed) {
1989 boolean old = this.rowSelectionAllowed;
1990 this.rowSelectionAllowed = rowSelectionAllowed;
1991 if (old != rowSelectionAllowed) {
1992 repaint();
1993 }
1994 firePropertyChange("rowSelectionAllowed", old, rowSelectionAllowed);
1995 }
1996
1997 /**
1998 * Returns true if rows can be selected.
1999 *
2000 * @return true if rows can be selected, otherwise false
2001 * @see #setRowSelectionAllowed
2002 */
2003 public boolean getRowSelectionAllowed() {
2004 return rowSelectionAllowed;
2005 }
2006
2007 /**
2008 * Sets whether the columns in this model can be selected.
2009 *
2010 * @param columnSelectionAllowed true if this model will allow column selection
2011 * @see #getColumnSelectionAllowed
2012 */
2013 @BeanProperty(visualUpdate = true, description
2014 = "If true, an entire column is selected for each selected cell.")
2015 public void setColumnSelectionAllowed(boolean columnSelectionAllowed) {
2016 boolean old = columnModel.getColumnSelectionAllowed();
2017 columnModel.setColumnSelectionAllowed(columnSelectionAllowed);
2018 if (old != columnSelectionAllowed) {
2019 repaint();
2020 }
2021 firePropertyChange("columnSelectionAllowed", old, columnSelectionAllowed);
2022 }
2023
2024 /**
2025 * Returns true if columns can be selected.
2026 *
2027 * @return true if columns can be selected, otherwise false
2028 * @see #setColumnSelectionAllowed
2029 */
2030 public boolean getColumnSelectionAllowed() {
2031 return columnModel.getColumnSelectionAllowed();
2032 }
2033
2034 /**
2035 * Sets whether this table allows both a column selection and a
2036 * row selection to exist simultaneously. When set,
2037 * the table treats the intersection of the row and column selection
2038 * models as the selected cells. Override <code>isCellSelected</code> to
2039 * change this default behavior. This method is equivalent to setting
2040 * both the <code>rowSelectionAllowed</code> property and
2041 * <code>columnSelectionAllowed</code> property of the
2042 * <code>columnModel</code> to the supplied value.
2043 *
2044 * @param cellSelectionEnabled true if simultaneous row and column
2045 * selection is allowed
2046 * @see #getCellSelectionEnabled
2047 * @see #isCellSelected
2048 */
2049 @BeanProperty(visualUpdate = true, description
2050 = "Select a rectangular region of cells rather than rows or columns.")
2051 public void setCellSelectionEnabled(boolean cellSelectionEnabled) {
2052 setRowSelectionAllowed(cellSelectionEnabled);
2053 setColumnSelectionAllowed(cellSelectionEnabled);
2054 boolean old = this.cellSelectionEnabled;
2055 this.cellSelectionEnabled = cellSelectionEnabled;
2056 firePropertyChange("cellSelectionEnabled", old, cellSelectionEnabled);
2057 }
2058
2059 /**
2060 * Returns true if both row and column selection models are enabled.
2061 * Equivalent to <code>getRowSelectionAllowed() &&
2062 * getColumnSelectionAllowed()</code>.
2063 *
2064 * @return true if both row and column selection models are enabled
2065 *
2066 * @see #setCellSelectionEnabled
2067 */
2068 public boolean getCellSelectionEnabled() {
2069 return getRowSelectionAllowed() && getColumnSelectionAllowed();
2070 }
2218 selectionModel.removeSelectionInterval(boundRow(index0), boundRow(index1));
2219 }
2220
2221 /**
2222 * Deselects the columns from <code>index0</code> to <code>index1</code>, inclusive.
2223 *
2224 * @exception IllegalArgumentException if <code>index0</code> or
2225 * <code>index1</code> lie outside
2226 * [0, <code>getColumnCount()</code>-1]
2227 * @param index0 one end of the interval
2228 * @param index1 the other end of the interval
2229 */
2230 public void removeColumnSelectionInterval(int index0, int index1) {
2231 columnModel.getSelectionModel().removeSelectionInterval(boundColumn(index0), boundColumn(index1));
2232 }
2233
2234 /**
2235 * Returns the index of the first selected row, -1 if no row is selected.
2236 * @return the index of the first selected row
2237 */
2238 @BeanProperty(bound = false)
2239 public int getSelectedRow() {
2240 return selectionModel.getMinSelectionIndex();
2241 }
2242
2243 /**
2244 * Returns the index of the first selected column,
2245 * -1 if no column is selected.
2246 * @return the index of the first selected column
2247 */
2248 @BeanProperty(bound = false)
2249 public int getSelectedColumn() {
2250 return columnModel.getSelectionModel().getMinSelectionIndex();
2251 }
2252
2253 /**
2254 * Returns the indices of all selected rows.
2255 *
2256 * @return an array of integers containing the indices of all selected rows,
2257 * or an empty array if no row is selected
2258 * @see #getSelectedRow
2259 */
2260 @BeanProperty(bound = false)
2261 public int[] getSelectedRows() {
2262 int iMin = selectionModel.getMinSelectionIndex();
2263 int iMax = selectionModel.getMaxSelectionIndex();
2264
2265 if ((iMin == -1) || (iMax == -1)) {
2266 return new int[0];
2267 }
2268
2269 int[] rvTmp = new int[1+ (iMax - iMin)];
2270 int n = 0;
2271 for(int i = iMin; i <= iMax; i++) {
2272 if (selectionModel.isSelectedIndex(i)) {
2273 rvTmp[n++] = i;
2274 }
2275 }
2276 int[] rv = new int[n];
2277 System.arraycopy(rvTmp, 0, rv, 0, n);
2278 return rv;
2279 }
2280
2281 /**
2282 * Returns the indices of all selected columns.
2283 *
2284 * @return an array of integers containing the indices of all selected columns,
2285 * or an empty array if no column is selected
2286 * @see #getSelectedColumn
2287 */
2288 @BeanProperty(bound = false)
2289 public int[] getSelectedColumns() {
2290 return columnModel.getSelectedColumns();
2291 }
2292
2293 /**
2294 * Returns the number of selected rows.
2295 *
2296 * @return the number of selected rows, 0 if no rows are selected
2297 */
2298 @BeanProperty(bound = false)
2299 public int getSelectedRowCount() {
2300 int iMin = selectionModel.getMinSelectionIndex();
2301 int iMax = selectionModel.getMaxSelectionIndex();
2302 int count = 0;
2303
2304 for(int i = iMin; i <= iMax; i++) {
2305 if (selectionModel.isSelectedIndex(i)) {
2306 count++;
2307 }
2308 }
2309 return count;
2310 }
2311
2312 /**
2313 * Returns the number of selected columns.
2314 *
2315 * @return the number of selected columns, 0 if no columns are selected
2316 */
2317 @BeanProperty(bound = false)
2318 public int getSelectedColumnCount() {
2319 return columnModel.getSelectedColumnCount();
2320 }
2321
2322 /**
2323 * Returns true if the specified index is in the valid range of rows,
2324 * and the row at that index is selected.
2325 *
2326 * @param row a row in the row model
2327 * @return true if <code>row</code> is a valid index and the row at
2328 * that index is selected (where 0 is the first row)
2329 */
2330 public boolean isRowSelected(int row) {
2331 return selectionModel.isSelectedIndex(row);
2332 }
2333
2334 /**
2335 * Returns true if the specified index is in the valid range of columns,
2336 * and the column at that index is selected.
2337 *
2485 return selectionForeground;
2486 }
2487
2488 /**
2489 * Sets the foreground color for selected cells. Cell renderers
2490 * can use this color to render text and graphics for selected
2491 * cells.
2492 * <p>
2493 * The default value of this property is defined by the look
2494 * and feel implementation.
2495 * <p>
2496 * This is a <a href="http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html">JavaBeans</a> bound property.
2497 *
2498 * @param selectionForeground the <code>Color</code> to use in the foreground
2499 * for selected list items
2500 * @see #getSelectionForeground
2501 * @see #setSelectionBackground
2502 * @see #setForeground
2503 * @see #setBackground
2504 * @see #setFont
2505 */
2506 @BeanProperty(description
2507 = "A default foreground color for selected cells.")
2508 public void setSelectionForeground(Color selectionForeground) {
2509 Color old = this.selectionForeground;
2510 this.selectionForeground = selectionForeground;
2511 firePropertyChange("selectionForeground", old, selectionForeground);
2512 repaint();
2513 }
2514
2515 /**
2516 * Returns the background color for selected cells.
2517 *
2518 * @return the <code>Color</code> used for the background of selected list items
2519 * @see #setSelectionBackground
2520 * @see #setSelectionForeground
2521 */
2522 public Color getSelectionBackground() {
2523 return selectionBackground;
2524 }
2525
2526 /**
2527 * Sets the background color for selected cells. Cell renderers
2528 * can use this color to the fill selected cells.
2529 * <p>
2530 * The default value of this property is defined by the look
2531 * and feel implementation.
2532 * <p>
2533 * This is a <a href="http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html">JavaBeans</a> bound property.
2534 *
2535 * @param selectionBackground the <code>Color</code> to use for the background
2536 * of selected cells
2537 * @see #getSelectionBackground
2538 * @see #setSelectionForeground
2539 * @see #setForeground
2540 * @see #setBackground
2541 * @see #setFont
2542 */
2543 @BeanProperty(description
2544 = "A default background color for selected cells.")
2545 public void setSelectionBackground(Color selectionBackground) {
2546 Color old = this.selectionBackground;
2547 this.selectionBackground = selectionBackground;
2548 firePropertyChange("selectionBackground", old, selectionBackground);
2549 repaint();
2550 }
2551
2552 /**
2553 * Returns the <code>TableColumn</code> object for the column in the table
2554 * whose identifier is equal to <code>identifier</code>, when compared using
2555 * <code>equals</code>.
2556 *
2557 * @return the <code>TableColumn</code> object that matches the identifier
2558 * @exception IllegalArgumentException if <code>identifier</code> is <code>null</code> or no <code>TableColumn</code> has this identifier
2559 *
2560 * @param identifier the identifier object
2561 */
2562 public TableColumn getColumn(Object identifier) {
2563 TableColumnModel cm = getColumnModel();
2564 int columnIndex = cm.getColumnIndex(identifier);
2640 * @since 1.6
2641 */
2642 public int convertRowIndexToModel(int viewRowIndex) {
2643 RowSorter<?> sorter = getRowSorter();
2644 if (sorter != null) {
2645 return sorter.convertRowIndexToModel(viewRowIndex);
2646 }
2647 return viewRowIndex;
2648 }
2649
2650 /**
2651 * Returns the number of rows that can be shown in the
2652 * <code>JTable</code>, given unlimited space. If a
2653 * <code>RowSorter</code> with a filter has been specified, the
2654 * number of rows returned may differ from that of the underlying
2655 * <code>TableModel</code>.
2656 *
2657 * @return the number of rows shown in the <code>JTable</code>
2658 * @see #getColumnCount
2659 */
2660 @BeanProperty(bound = false)
2661 public int getRowCount() {
2662 RowSorter<?> sorter = getRowSorter();
2663 if (sorter != null) {
2664 return sorter.getViewRowCount();
2665 }
2666 return getModel().getRowCount();
2667 }
2668
2669 /**
2670 * Returns the number of columns in the column model. Note that this may
2671 * be different from the number of columns in the table model.
2672 *
2673 * @return the number of columns in the table
2674 * @see #getRowCount
2675 * @see #removeColumn
2676 */
2677 @BeanProperty(bound = false)
2678 public int getColumnCount() {
2679 return getColumnModel().getColumnCount();
2680 }
2681
2682 /**
2683 * Returns the name of the column appearing in the view at
2684 * column position <code>column</code>.
2685 *
2686 * @param column the column in the view being queried
2687 * @return the name of the column at position <code>column</code>
2688 in the view where the first column is column 0
2689 */
2690 public String getColumnName(int column) {
2691 return getModel().getColumnName(convertColumnIndexToModel(column));
2692 }
2693
2694 /**
2695 * Returns the type of the column appearing in the view at
2696 * column position <code>column</code>.
2697 *
3526 editorComp.validate();
3527 editorComp.repaint();
3528
3529 setCellEditor(editor);
3530 setEditingRow(row);
3531 setEditingColumn(column);
3532 editor.addCellEditorListener(this);
3533
3534 return true;
3535 }
3536 return false;
3537 }
3538
3539 /**
3540 * Returns true if a cell is being edited.
3541 *
3542 * @return true if the table is editing a cell
3543 * @see #editingColumn
3544 * @see #editingRow
3545 */
3546 @BeanProperty(bound = false)
3547 public boolean isEditing() {
3548 return cellEditor != null;
3549 }
3550
3551 /**
3552 * Returns the component that is handling the editing session.
3553 * If nothing is being edited, returns null.
3554 *
3555 * @return Component handling editing session
3556 */
3557 @BeanProperty(bound = false)
3558 public Component getEditorComponent() {
3559 return editorComp;
3560 }
3561
3562 /**
3563 * Returns the index of the column that contains the cell currently
3564 * being edited. If nothing is being edited, returns -1.
3565 *
3566 * @return the index of the column that contains the cell currently
3567 * being edited; returns -1 if nothing being edited
3568 * @see #editingRow
3569 */
3570 public int getEditingColumn() {
3571 return editingColumn;
3572 }
3573
3574 /**
3575 * Returns the index of the row that contains the cell currently
3576 * being edited. If nothing is being edited, returns -1.
3577 *
3584 }
3585
3586 //
3587 // Managing TableUI
3588 //
3589
3590 /**
3591 * Returns the L&F object that renders this component.
3592 *
3593 * @return the <code>TableUI</code> object that renders this component
3594 */
3595 public TableUI getUI() {
3596 return (TableUI)ui;
3597 }
3598
3599 /**
3600 * Sets the L&F object that renders this component and repaints.
3601 *
3602 * @param ui the TableUI L&F object
3603 * @see UIDefaults#getUI
3604 */
3605 @BeanProperty(hidden = true, visualUpdate = true, description
3606 = "The UI object that implements the Component's LookAndFeel.")
3607 public void setUI(TableUI ui) {
3608 if (this.ui != ui) {
3609 super.setUI(ui);
3610 repaint();
3611 }
3612 }
3613
3614 /**
3615 * Notification from the <code>UIManager</code> that the L&F has changed.
3616 * Replaces the current UI object with the latest version from the
3617 * <code>UIManager</code>.
3618 *
3619 * @see JComponent#updateUI
3620 */
3621 public void updateUI() {
3622 // Update the UIs of the cell renderers, cell editors and header renderers.
3623 TableColumnModel cm = getColumnModel();
3624 for(int column = 0; column < cm.getColumnCount(); column++) {
3625 TableColumn aColumn = cm.getColumn(column);
3626 SwingUtilities.updateRendererOrEditorUI(aColumn.getCellRenderer());
3642
3643 // Update the UI of the table header
3644 if (tableHeader != null && tableHeader.getParent() == null) {
3645 tableHeader.updateUI();
3646 }
3647
3648 // Update UI applied to parent ScrollPane
3649 configureEnclosingScrollPaneUI();
3650
3651 setUI((TableUI)UIManager.getUI(this));
3652 }
3653
3654 /**
3655 * Returns the suffix used to construct the name of the L&F class used to
3656 * render this component.
3657 *
3658 * @return the string "TableUI"
3659 * @see JComponent#getUIClassID
3660 * @see UIDefaults#getUI
3661 */
3662 @BeanProperty(bound = false)
3663 public String getUIClassID() {
3664 return uiClassID;
3665 }
3666
3667
3668 //
3669 // Managing models
3670 //
3671
3672 /**
3673 * Sets the data model for this table to <code>newModel</code> and registers
3674 * with it for listener notifications from the new data model.
3675 *
3676 * @param dataModel the new data source for this table
3677 * @exception IllegalArgumentException if <code>newModel</code> is <code>null</code>
3678 * @see #getModel
3679 */
3680 @BeanProperty(description
3681 = "The model that is the source of the data for this view.")
3682 public void setModel(TableModel dataModel) {
3683 if (dataModel == null) {
3684 throw new IllegalArgumentException("Cannot set a null TableModel");
3685 }
3686 if (this.dataModel != dataModel) {
3687 TableModel old = this.dataModel;
3688 if (old != null) {
3689 old.removeTableModelListener(this);
3690 }
3691 this.dataModel = dataModel;
3692 dataModel.addTableModelListener(this);
3693
3694 tableChanged(new TableModelEvent(dataModel, TableModelEvent.HEADER_ROW));
3695
3696 firePropertyChange("model", old, dataModel);
3697
3698 if (getAutoCreateRowSorter()) {
3699 setRowSorter(new TableRowSorter<TableModel>(dataModel));
3700 }
3701 }
3703
3704 /**
3705 * Returns the <code>TableModel</code> that provides the data displayed by this
3706 * <code>JTable</code>.
3707 *
3708 * @return the <code>TableModel</code> that provides the data displayed by this <code>JTable</code>
3709 * @see #setModel
3710 */
3711 public TableModel getModel() {
3712 return dataModel;
3713 }
3714
3715 /**
3716 * Sets the column model for this table to <code>newModel</code> and registers
3717 * for listener notifications from the new column model. Also sets
3718 * the column model of the <code>JTableHeader</code> to <code>columnModel</code>.
3719 *
3720 * @param columnModel the new data source for this table
3721 * @exception IllegalArgumentException if <code>columnModel</code> is <code>null</code>
3722 * @see #getColumnModel
3723 */
3724 @BeanProperty(description
3725 = "The object governing the way columns appear in the view.")
3726 public void setColumnModel(TableColumnModel columnModel) {
3727 if (columnModel == null) {
3728 throw new IllegalArgumentException("Cannot set a null ColumnModel");
3729 }
3730 TableColumnModel old = this.columnModel;
3731 if (columnModel != old) {
3732 if (old != null) {
3733 old.removeColumnModelListener(this);
3734 }
3735 this.columnModel = columnModel;
3736 columnModel.addColumnModelListener(this);
3737
3738 // Set the column model of the header as well.
3739 if (tableHeader != null) {
3740 tableHeader.setColumnModel(columnModel);
3741 }
3742
3743 firePropertyChange("columnModel", old, columnModel);
3744 resizeAndRepaint();
3745 }
3746 }
3747
3748 /**
3749 * Returns the <code>TableColumnModel</code> that contains all column information
3750 * of this table.
3751 *
3752 * @return the object that provides the column state of the table
3753 * @see #setColumnModel
3754 */
3755 public TableColumnModel getColumnModel() {
3756 return columnModel;
3757 }
3758
3759 /**
3760 * Sets the row selection model for this table to <code>newModel</code>
3761 * and registers for listener notifications from the new selection model.
3762 *
3763 * @param newModel the new selection model
3764 * @exception IllegalArgumentException if <code>newModel</code> is <code>null</code>
3765 * @see #getSelectionModel
3766 */
3767 @BeanProperty(description
3768 = "The selection model for rows.")
3769 public void setSelectionModel(ListSelectionModel newModel) {
3770 if (newModel == null) {
3771 throw new IllegalArgumentException("Cannot set a null SelectionModel");
3772 }
3773
3774 ListSelectionModel oldModel = selectionModel;
3775
3776 if (newModel != oldModel) {
3777 if (oldModel != null) {
3778 oldModel.removeListSelectionListener(this);
3779 }
3780
3781 selectionModel = newModel;
3782 newModel.addListSelectionListener(this);
3783
3784 firePropertyChange("selectionModel", oldModel, newModel);
3785 repaint();
3786 }
3787 }
3788
4736 * Application code will not use these methods explicitly, they
4737 * are used internally by JTable.
4738 *
4739 * @param e the event received
4740 * @see CellEditorListener
4741 */
4742 public void editingCanceled(ChangeEvent e) {
4743 removeEditor();
4744 }
4745
4746 //
4747 // Implementing the Scrollable interface
4748 //
4749
4750 /**
4751 * Sets the preferred size of the viewport for this table.
4752 *
4753 * @param size a <code>Dimension</code> object specifying the <code>preferredSize</code> of a
4754 * <code>JViewport</code> whose view is this table
4755 * @see Scrollable#getPreferredScrollableViewportSize
4756 */
4757 @BeanProperty(bound = false, description
4758 = "The preferred size of the viewport.")
4759 public void setPreferredScrollableViewportSize(Dimension size) {
4760 preferredViewportSize = size;
4761 }
4762
4763 /**
4764 * Returns the preferred size of the viewport for this table.
4765 *
4766 * @return a <code>Dimension</code> object containing the <code>preferredSize</code> of the <code>JViewport</code>
4767 * which displays this table
4768 * @see Scrollable#getPreferredScrollableViewportSize
4769 */
4770 public Dimension getPreferredScrollableViewportSize() {
4771 return preferredViewportSize;
4772 }
4773
4774 /**
4775 * Returns the scroll increment (in pixels) that completely exposes one new
4776 * row or column (depending on the orientation).
4777 * <p>
4778 * This method is called each time the user requests a unit scroll.
5174 return rect.y + rect.height;
5175 }
5176 else if (getComponentOrientation().isLeftToRight()) {
5177 return rect.x + rect.width;
5178 }
5179 else { // Horizontal, right-to-left
5180 return rect.x;
5181 }
5182 }
5183
5184 /**
5185 * Returns false if <code>autoResizeMode</code> is set to
5186 * <code>AUTO_RESIZE_OFF</code>, which indicates that the
5187 * width of the viewport does not determine the width
5188 * of the table. Otherwise returns true.
5189 *
5190 * @return false if <code>autoResizeMode</code> is set
5191 * to <code>AUTO_RESIZE_OFF</code>, otherwise returns true
5192 * @see Scrollable#getScrollableTracksViewportWidth
5193 */
5194 @BeanProperty(bound = false)
5195 public boolean getScrollableTracksViewportWidth() {
5196 return !(autoResizeMode == AUTO_RESIZE_OFF);
5197 }
5198
5199 /**
5200 * Returns {@code false} to indicate that the height of the viewport does
5201 * not determine the height of the table, unless
5202 * {@code getFillsViewportHeight} is {@code true} and the preferred height
5203 * of the table is smaller than the viewport's height.
5204 *
5205 * @return {@code false} unless {@code getFillsViewportHeight} is
5206 * {@code true} and the table needs to be stretched to fill
5207 * the viewport
5208 * @see Scrollable#getScrollableTracksViewportHeight
5209 * @see #setFillsViewportHeight
5210 * @see #getFillsViewportHeight
5211 */
5212 @BeanProperty(bound = false)
5213 public boolean getScrollableTracksViewportHeight() {
5214 Container parent = SwingUtilities.getUnwrappedParent(this);
5215 return getFillsViewportHeight()
5216 && parent instanceof JViewport
5217 && parent.getHeight() > getPreferredSize().height;
5218 }
5219
5220 /**
5221 * Sets whether or not this table is always made large enough
5222 * to fill the height of an enclosing viewport. If the preferred
5223 * height of the table is smaller than the viewport, then the table
5224 * will be stretched to fill the viewport. In other words, this
5225 * ensures the table is never smaller than the viewport.
5226 * The default for this property is {@code false}.
5227 *
5228 * @param fillsViewportHeight whether or not this table is always
5229 * made large enough to fill the height of an enclosing
5230 * viewport
5231 * @see #getFillsViewportHeight
5232 * @see #getScrollableTracksViewportHeight
5233 * @since 1.6
5234 */
5235 @BeanProperty(description
5236 = "Whether or not this table is always made large enough to fill the height of an enclosing viewport")
5237 public void setFillsViewportHeight(boolean fillsViewportHeight) {
5238 boolean old = this.fillsViewportHeight;
5239 this.fillsViewportHeight = fillsViewportHeight;
5240 resizeAndRepaint();
5241 firePropertyChange("fillsViewportHeight", old, fillsViewportHeight);
5242 }
5243
5244 /**
5245 * Returns whether or not this table is always made large enough
5246 * to fill the height of an enclosing viewport.
5247 *
5248 * @return whether or not this table is always made large enough
5249 * to fill the height of an enclosing viewport
5250 * @see #setFillsViewportHeight
5251 * @since 1.6
5252 */
5253 public boolean getFillsViewportHeight() {
5254 return fillsViewportHeight;
5255 }
5256
5613 }
5614
5615 /**
5616 * Returns the active cell editor, which is {@code null} if the table
5617 * is not currently editing.
5618 *
5619 * @return the {@code TableCellEditor} that does the editing,
5620 * or {@code null} if the table is not currently editing.
5621 * @see #cellEditor
5622 * @see #getCellEditor(int, int)
5623 */
5624 public TableCellEditor getCellEditor() {
5625 return cellEditor;
5626 }
5627
5628 /**
5629 * Sets the active cell editor.
5630 *
5631 * @param anEditor the active cell editor
5632 * @see #cellEditor
5633 */
5634 @BeanProperty(description
5635 = "The table's active cell editor.")
5636 public void setCellEditor(TableCellEditor anEditor) {
5637 TableCellEditor oldEditor = cellEditor;
5638 cellEditor = anEditor;
5639 firePropertyChange("tableCellEditor", oldEditor, anEditor);
5640 }
5641
5642 /**
5643 * Sets the <code>editingColumn</code> variable.
5644 * @param aColumn the column of the cell to be edited
5645 *
5646 * @see #editingColumn
5647 */
5648 public void setEditingColumn(int aColumn) {
5649 editingColumn = aColumn;
5650 }
5651
5652 /**
5653 * Sets the <code>editingRow</code> variable.
5654 * @param aRow the row of the cell to be edited
5655 *
6608 }
6609
6610 return retVal;
6611 }
6612 }
6613 }
6614
6615 /////////////////
6616 // Accessibility support
6617 ////////////////
6618
6619 /**
6620 * Gets the AccessibleContext associated with this JTable.
6621 * For tables, the AccessibleContext takes the form of an
6622 * AccessibleJTable.
6623 * A new AccessibleJTable instance is created if necessary.
6624 *
6625 * @return an AccessibleJTable that serves as the
6626 * AccessibleContext of this JTable
6627 */
6628 @BeanProperty(bound = false)
6629 public AccessibleContext getAccessibleContext() {
6630 if (accessibleContext == null) {
6631 accessibleContext = new AccessibleJTable();
6632 }
6633 return accessibleContext;
6634 }
6635
6636 //
6637 // *** should also implement AccessibleSelection?
6638 // *** and what's up with keyboard navigation/manipulation?
6639 //
6640 /**
6641 * This class implements accessibility support for the
6642 * <code>JTable</code> class. It provides an implementation of the
6643 * Java Accessibility API appropriate to table user-interface elements.
6644 * <p>
6645 * <strong>Warning:</strong>
6646 * Serialized objects of this class will not be compatible with
6647 * future Swing releases. The current serialization support is
6648 * appropriate for short term storage or RMI between applications running
|