Merge from the pain train
[official-gcc.git] / libjava / javax / swing / JTable.java
blobca38aa0ba0952516a714bb3f9b9b6fcdfc768d50
1 /* JTable.java --
2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing;
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Dimension;
44 import java.awt.Point;
45 import java.awt.Rectangle;
46 import java.util.Hashtable;
47 import java.util.Vector;
49 import javax.accessibility.Accessible;
50 import javax.accessibility.AccessibleContext;
51 import javax.swing.event.CellEditorListener;
52 import javax.swing.event.ChangeEvent;
53 import javax.swing.event.ListSelectionEvent;
54 import javax.swing.event.ListSelectionListener;
55 import javax.swing.event.TableColumnModelEvent;
56 import javax.swing.event.TableColumnModelListener;
57 import javax.swing.event.TableModelEvent;
58 import javax.swing.event.TableModelListener;
59 import javax.swing.plaf.TableUI;
60 import javax.swing.table.DefaultTableCellRenderer;
61 import javax.swing.table.DefaultTableColumnModel;
62 import javax.swing.table.DefaultTableModel;
63 import javax.swing.table.JTableHeader;
64 import javax.swing.table.TableCellEditor;
65 import javax.swing.table.TableCellRenderer;
66 import javax.swing.table.TableColumn;
67 import javax.swing.table.TableColumnModel;
68 import javax.swing.table.TableModel;
70 public class JTable extends JComponent
71 implements TableModelListener, Scrollable, TableColumnModelListener,
72 ListSelectionListener, CellEditorListener, Accessible
74 private static final long serialVersionUID = 3876025080382781659L;
77 /**
78 * When resizing columns, do not automatically change any columns. In this
79 * case the table should be enclosed in a {@link JScrollPane} in order to
80 * accomodate cases in which the table size exceeds its visible area.
82 public static final int AUTO_RESIZE_OFF = 0;
84 /**
85 * When resizing column <code>i</code>, automatically change only the
86 * single column <code>i+1</code> to provide or absorb excess space
87 * requirements.
89 public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
91 /**
92 * When resizing column <code>i</code> in a table of <code>n</code>
93 * columns, automatically change all columns in the range <code>[i+1,
94 * n)</code>, uniformly, to provide or absorb excess space requirements.
96 public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
98 /**
99 * When resizing column <code>i</code> in a table of <code>n</code>
100 * columns, automatically change all columns in the range <code>[0,
101 * n)</code> (with the exception of column i) uniformly, to provide or
102 * absorb excess space requirements.
104 public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
107 * When resizing column <code>i</code> in a table of <code>n</code>
108 * columns, automatically change column <code>n-1</code> (the last column
109 * in the table) to provide or absorb excess space requirements.
111 public static final int AUTO_RESIZE_LAST_COLUMN = 3;
115 * A table mapping {@link java.lang.Class} objects to
116 * {@link TableCellEditor} objects. This table is consulted by the
117 * FIXME
119 protected Hashtable defaultEditorsByColumnClass;
122 * A table mapping {@link java.lang.Class} objects to
123 * {@link TableCellEditor} objects. This table is consulted by the
124 * FIXME
126 protected Hashtable defaultRenderersByColumnClass;
129 * The column that is edited, -1 if the table is not edited currently.
131 protected int editingColumn;
134 * The row that is edited, -1 if the table is not edited currently.
136 protected int editingRow;
139 * The component that is used for editing.
140 * <code>null</code> if the table is not editing currently.
143 protected transient Component editorComp;
146 * Whether or not the table should automatically compute a matching
147 * {@link TableColumnModel} and assign it to the {@link #columnModel}
148 * property when the {@link #dataModel} property is changed.
150 * @see #setModel()
151 * @see #createColumnsFromModel()
152 * @see #setColumnModel()
153 * @see #setAutoCreateColumnsFromModel()
154 * @see #getAutoCreateColumnsFromModel()
156 protected boolean autoCreateColumnsFromModel;
159 * A numeric code specifying the resizing behavior of the table. Must be
160 * one of {@link #AUTO_RESIZE_ALL_COLUMNS} (the default), {@link
161 * #AUTO_RESIZE_LAST_COLUMN}, {@link #AUTO_RESIZE_NEXT_COLUMN}, {@link
162 * #AUTO_RESIZE_SUBSEQUENT_COLUMNS}, or {@link #AUTO_RESIZE_OFF}.
164 * @see #doLayout()
165 * @see #setAutoResizeMode()
166 * @see #getAutoResizeMode()
168 protected int autoResizeMode;
171 * The height in pixels of any row of the table. All rows in a table are
172 * of uniform height. This differs from column width, which varies on a
173 * per-column basis, and is stored in the individual columns of the
174 * {@link #columnModel}.
176 * @see #getRowHeight()
177 * @see #setRowHeight()
178 * @see TableColumn#getWidth()
179 * @see TableColumn#setWidth()
181 protected int rowHeight;
184 * The height in pixels of the gap left between any two rows of the table.
186 * @see #setRowMargin()
187 * @see #getRowHeight()
188 * @see #getIntercellSpacing()
189 * @see #setIntercellSpacing()
190 * @see TableColumnModel#getColumnMargin()
191 * @see TableColumnModel#setColumnMargin()
193 protected int rowMargin;
196 * Whether or not the table should allow row selection. If the table
197 * allows both row <em>and</em> column selection, it is said to allow
198 * "cell selection". Previous versions of the JDK supported cell
199 * selection as an independent concept, but it is now represented solely
200 * in terms of simultaneous row and column selection.
202 * @see TableColumnModel#columnSelectionAllowed()
203 * @see #setRowSelectionAllowed()
204 * @see #getRowSelectionAllowed()
205 * @see #getCellSelectionEnabled()
206 * @see #setCellSelectionEnabled()
208 protected boolean rowSelectionAllowed;
211 * @deprecated Use {@link #rowSelectionAllowed}, {@link
212 * #columnSelectionAllowed}, or the combined methods {@link
213 * getCellSelectionEnabled} and {@link setCellSelectionEnabled}.
215 protected boolean cellSelectionEnabled;
218 * The model for data stored in the table. Confusingly, the published API
219 * requires that this field be called <code>dataModel</code>, despite its
220 * property name. The table listens to its model as a {@link
221 * TableModelListener}.
223 * @see #tableChanged()
224 * @see TableModel#addTableModelListener()
226 protected TableModel dataModel;
229 * <p>A model of various aspects of the columns of the table, <em>not
230 * including</em> the data stored in them. The {@link TableColumnModel}
231 * is principally concerned with holding a set of {@link TableColumn}
232 * objects, each of which describes the display parameters of a column
233 * and the numeric index of the column from the data model which the
234 * column is presenting.</p>
236 * <p>The TableColumnModel also contains a {@link ListSelectionModel} which
237 * indicates which columns are currently selected. This selection model
238 * works in combination with the {@link selectionModel} of the table
239 * itself to specify a <em>table selection</em>: a combination of row and
240 * column selections.</p>
242 * <p>Most application programmers do not need to work with this property
243 * at all: setting {@link #autoCreateColumnsFromModel} will construct the
244 * columnModel automatically, and the table acts as a facade for most of
245 * the interesting properties of the columnModel anyways.</p>
247 * @see #setColumnModel()
248 * @see #getColumnModel()
250 protected TableColumnModel columnModel;
253 * A model of the rows of this table which are currently selected. This
254 * model is used in combination with the column selection model held as a
255 * member of the {@link columnModel} property, to represent the rows and
256 * columns (or both: cells) of the table which are currently selected.
258 * @see #rowSelectionAllowed
259 * @see #setSelectionModel()
260 * @see #getSelectionModel()
261 * @see TableColumnModel#getSelectionModel()
262 * @see ListSelectionModel#addListSelectionListener()
264 protected ListSelectionModel selectionModel;
267 * The accessibleContext property.
269 protected AccessibleContext accessibleContext;
272 * The current cell editor.
274 protected TableCellEditor cellEditor;
277 * Whether or not drag-and-drop is enabled on this table.
279 * @see #setDragEnabled()
280 * @see #getDragEnabled()
282 private boolean dragEnabled;
285 * The color to paint the grid lines of the table, when either {@link
286 * #showHorizontalLines} or {@link #showVerticalLines} is set.
288 * @see #setGridColor()
289 * @see #getGridColor()
291 protected Color gridColor;
294 * The size this table would prefer its viewport assume, if it is
295 * contained in a {@link JScrollPane}.
297 * @see #setPreferredScrollableViewportSize()
298 * @see #getPreferredScrollableViewportSize()
300 protected Dimension preferredViewportSize;
303 * The color to paint the background of selected cells. Fires a property
304 * change event with name {@link #SELECTION_BACKGROUND_CHANGED_PROPERTY}
305 * when its value changes.
307 * @see #setSelectionBackground()
308 * @see #getSelectionBackground()
310 protected Color selectionBackground;
313 * The name carried in property change events when the {@link
314 * #selectionBackground} property changes.
316 private static final String SELECTION_BACKGROUND_CHANGED_PROPERTY = "selectionBackground";
319 * The color to paint the foreground of selected cells. Fires a property
320 * change event with name {@link #SELECTION_FOREGROUND_CHANGED_PROPERTY}
321 * when its value changes.
323 * @see #setSelectionForeground()
324 * @see #getSelectionForeground()
326 protected Color selectionForeground;
329 * The name carried in property change events when the
330 * {@link #selectionForeground} property changes.
332 private static final String SELECTION_FOREGROUND_CHANGED_PROPERTY = "selectionForeground";
335 * The showHorizontalLines property.
337 protected boolean showHorizontalLines;
340 * The showVerticalLines property.
342 protected boolean showVerticalLines;
345 * The tableHeader property.
347 protected JTableHeader tableHeader;
351 * Creates a new <code>JTable</code> instance.
353 public JTable ()
355 this(null, null, null);
359 * Creates a new <code>JTable</code> instance.
361 * @param numRows an <code>int</code> value
362 * @param numColumns an <code>int</code> value
364 public JTable (int numRows, int numColumns)
366 this(new DefaultTableModel(numRows, numColumns));
370 * Creates a new <code>JTable</code> instance.
372 * @param data an <code>Object[][]</code> value
373 * @param columnNames an <code>Object[]</code> value
375 public JTable(Object[][] data, Object[] columnNames)
377 this(new DefaultTableModel(data, columnNames));
381 * Creates a new <code>JTable</code> instance.
383 * @param dm a <code>TableModel</code> value
385 public JTable (TableModel dm)
387 this(dm, null, null);
391 * Creates a new <code>JTable</code> instance.
393 * @param dm a <code>TableModel</code> value
394 * @param cm a <code>TableColumnModel</code> value
396 public JTable (TableModel dm, TableColumnModel cm)
398 this(dm, cm, null);
402 * Creates a new <code>JTable</code> instance.
404 * @param dm a <code>TableModel</code> value
405 * @param cm a <code>TableColumnModel</code> value
406 * @param sm a <code>ListSelectionModel</code> value
408 public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm)
410 this.dataModel = dm == null ? createDefaultDataModel() : dm;
411 setSelectionModel(sm == null ? createDefaultSelectionModel() : sm);
413 this.columnModel = cm;
414 initializeLocalVars();
415 updateUI();
418 protected void initializeLocalVars()
420 this.autoCreateColumnsFromModel = false;
421 if (columnModel == null)
423 this.autoCreateColumnsFromModel = true;
424 createColumnsFromModel();
426 this.columnModel.addColumnModelListener(this);
428 this.defaultRenderersByColumnClass = new Hashtable();
429 createDefaultRenderers();
431 this.defaultEditorsByColumnClass = new Hashtable();
432 createDefaultEditors();
434 this.autoResizeMode = AUTO_RESIZE_ALL_COLUMNS;
435 this.rowHeight = 16;
436 this.rowMargin = 1;
437 this.rowSelectionAllowed = true;
438 // this.accessibleContext = new AccessibleJTable();
439 this.cellEditor = null;
440 this.dragEnabled = false;
441 this.preferredViewportSize = new Dimension(450,400);
442 this.showHorizontalLines = true;
443 this.showVerticalLines = true;
444 this.editingColumn = -1;
445 this.editingRow = -1;
446 setIntercellSpacing(new Dimension(1,1));
447 setTableHeader(createDefaultTableHeader());
451 * Creates a new <code>JTable</code> instance.
453 * @param data a <code>Vector</code> value
454 * @param columnNames a <code>Vector</code> value
456 public JTable(Vector data, Vector columnNames)
458 this(new DefaultTableModel(data, columnNames));
461 public void addColumn(TableColumn column)
463 if (column.getHeaderValue() == null)
465 String name = getColumnName(column.getModelIndex());
466 column.setHeaderValue(name);
469 columnModel.addColumn(column);
472 protected void createDefaultEditors()
474 //FIXME: Create the editor object.
477 protected void createDefaultRenderers()
479 //FIXME: Create the renderer object.
483 * @deprecated 1.0.2, replaced by <code>new JScrollPane(JTable)</code>
485 public static JScrollPane createScrollPaneForTable(JTable table)
487 return new JScrollPane(table);
490 protected TableColumnModel createDefaultColumnModel()
492 return new DefaultTableColumnModel();
495 protected TableModel createDefaultDataModel()
497 return new DefaultTableModel();
500 protected ListSelectionModel createDefaultSelectionModel()
502 return new DefaultListSelectionModel();
505 protected JTableHeader createDefaultTableHeader()
507 return new JTableHeader(columnModel);
510 private void createColumnsFromModel()
512 if (dataModel == null)
513 return;
515 TableColumnModel cm = createDefaultColumnModel();
517 for (int i = 0; i < dataModel.getColumnCount(); ++i)
519 cm.addColumn(new TableColumn(i));
521 this.setColumnModel(cm);
524 // listener support
526 public void columnAdded (TableColumnModelEvent event)
528 revalidate();
529 repaint();
532 public void columnMarginChanged (ChangeEvent event)
534 revalidate();
535 repaint();
538 public void columnMoved (TableColumnModelEvent event)
540 revalidate();
541 repaint();
544 public void columnRemoved (TableColumnModelEvent event)
546 revalidate();
547 repaint();
550 public void columnSelectionChanged (ListSelectionEvent event)
552 repaint();
555 public void editingCanceled (ChangeEvent event)
557 repaint();
560 public void editingStopped (ChangeEvent event)
562 repaint();
565 public void tableChanged (TableModelEvent event)
567 repaint();
570 public void valueChanged (ListSelectionEvent event)
572 repaint();
576 * Returns index of the column that contains specified point
577 * or -1 if this table doesn't contain this point.
579 * @param point point to identify the column
580 * @return index of the column that contains specified point or
581 * -1 if this table doesn't contain this point.
583 public int columnAtPoint(Point point)
585 int x0 = getLocation().x;
586 int ncols = getColumnCount();
587 Dimension gap = getIntercellSpacing();
588 TableColumnModel cols = getColumnModel();
589 int x = point.x;
591 for (int i = 0; i < ncols; ++i)
593 int width = cols.getColumn(i).getWidth() + (gap == null ? 0 : gap.width);
594 if (0 <= x && x < width)
595 return i;
596 x -= width;
599 return -1;
603 * Returns index of the row that contains specified point or
604 * -1 if this table doesn't contain this point.
606 * @param point point to identify the row
607 * @return index of the row that contains specified point or
608 * -1 if this table doesn't contain this point.
610 public int rowAtPoint(Point point)
612 int y0 = getLocation().y;
613 int nrows = getRowCount();
614 Dimension gap = getIntercellSpacing();
615 int height = getRowHeight() + (gap == null ? 0 : gap.height);
616 int y = point.y;
618 for (int i = 0; i < nrows; ++i)
620 if (0 <= y && y < height)
621 return i;
622 y -= height;
625 return -1;
628 /**
629 * Calculate the visible rectangle for a particular row and column. The
630 * row and column are specified in visual terms; the column may not match
631 * the {@link #dataModel} column.
633 * @param row the visible row to get the cell rectangle of
635 * @param column the visible column to get the cell rectangle of, which may
636 * differ from the {@link #dataModel} column
638 * @param includeSpacing whether or not to include the cell margins in the
639 * resulting cell. If <code>false</code>, the result will only contain the
640 * inner area of the target cell, not including its margins.
642 * @return a rectangle enclosing the specified cell
644 public Rectangle getCellRect(int row,
645 int column,
646 boolean includeSpacing)
648 int height = getHeight();
649 int width = columnModel.getColumn(column).getWidth();
650 int x_gap = columnModel.getColumnMargin();
651 int y_gap = rowMargin;
653 column = Math.max(0, Math.min(column, getColumnCount() - 1));
654 row = Math.max(0, Math.min(row, getRowCount() - 1));
656 int x = 0;
657 int y = (height + y_gap) * row;
659 for (int i = 0; i < column; ++i)
661 x += columnModel.getColumn(i).getWidth();
662 x += x_gap;
665 if (includeSpacing)
666 return new Rectangle(x, y, width, height);
667 else
668 return new Rectangle(x, y, width - x_gap, height - y_gap);
671 public void clearSelection()
673 selectionModel.clearSelection();
677 * Get the value of the {@link #selectedRow} property by delegation to
678 * the {@link ListSelectionModel#getMinSelectionIndex} method of the
679 * {@link #selectionModel} field.
681 * @return The current value of the selectedRow property
683 public int getSelectedRow ()
685 return selectionModel.getMinSelectionIndex();
689 * Get the value of the {@link #selectionModel} property.
691 * @return The current value of the property
693 public ListSelectionModel getSelectionModel()
695 if (! rowSelectionAllowed)
696 return null;
698 return selectionModel;
701 public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
703 if (orientation == SwingConstants.VERTICAL)
704 return visibleRect.height * direction;
705 else
706 return visibleRect.width * direction;
710 * Get the value of the {@link #scrollableTracksViewportHeight} property.
712 * @return The constant value <code>false</code>
715 public boolean getScrollableTracksViewportHeight()
717 return false;
721 * Get the value of the {@link #scrollableTracksViewportWidth} property.
723 * @return <code>true</code> unless the {@link autoResizeMode} prperty is
724 * <code>AUTO_RESIZE_OFF</code>
727 public boolean getScrollableTracksViewportWidth()
729 if (autoResizeMode == AUTO_RESIZE_OFF)
730 return false;
731 else
732 return true;
735 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
737 // FIXME: I don't exactly know what sun does here. in both cases they
738 // pick values which do *not* simply expose the next cell in a given
739 // scroll direction.
741 if (orientation == SwingConstants.VERTICAL)
742 return rowHeight;
743 else
745 int sum = 0;
746 for (int i = 0; i < getColumnCount(); ++i)
747 sum += columnModel.getColumn(0).getWidth();
748 return getColumnCount() == 0 ? 10 : sum / getColumnCount();
753 public TableCellEditor getCellEditor(int row, int column)
755 TableCellEditor editor = columnModel.getColumn(column).getCellEditor();
757 if (editor == null)
758 editor = getDefaultEditor(dataModel.getColumnClass(column));
760 return editor;
763 public TableCellEditor getDefaultEditor(Class columnClass)
765 if (defaultEditorsByColumnClass.containsKey(columnClass))
766 return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass);
767 else
769 // FIXME: We have at least an editor for Object.class in our defaults.
770 TableCellEditor r = new DefaultCellEditor(new JTextField());
771 defaultEditorsByColumnClass.put(columnClass, r);
772 return r;
778 public TableCellRenderer getCellRenderer(int row, int column)
780 TableCellRenderer renderer =
781 columnModel.getColumn(column).getCellRenderer();
783 if (renderer == null)
784 renderer = getDefaultRenderer(dataModel.getColumnClass(column));
786 return renderer;
789 public void setDefaultRenderer(Class columnClass, TableCellRenderer rend)
791 defaultRenderersByColumnClass.put(columnClass, rend);
794 public TableCellRenderer getDefaultRenderer(Class columnClass)
796 if (defaultRenderersByColumnClass.containsKey(columnClass))
797 return (TableCellRenderer) defaultRenderersByColumnClass.get(columnClass);
798 else
800 TableCellRenderer r = new DefaultTableCellRenderer();
801 defaultRenderersByColumnClass.put(columnClass, r);
802 return r;
806 public int convertColumnIndexToModel(int vc)
808 if (vc < 0)
809 return vc;
810 else if (vc > getColumnCount())
811 return -1;
812 else
813 return columnModel.getColumn(vc).getModelIndex();
816 public int convertColumnIndexToView(int mc)
818 if (mc < 0)
819 return mc;
820 int ncols = getColumnCount();
821 for (int vc = 0; vc < ncols; ++vc)
823 if (columnModel.getColumn(vc).getModelIndex() == mc)
824 return vc;
826 return -1;
829 public Component prepareRenderer(TableCellRenderer renderer,
830 int row,
831 int column)
833 boolean rsa = getRowSelectionAllowed();
834 boolean csa = getColumnSelectionAllowed();
835 boolean rs = rsa ? getSelectionModel().isSelectedIndex(row) : false;
836 boolean cs = csa ? columnModel.getSelectionModel().isSelectedIndex(column) : false;
837 boolean isSelected = ((rsa && csa && rs && cs)
838 || (rsa && !csa && rs)
839 || (!rsa && csa && cs));
841 return renderer.getTableCellRendererComponent(this,
842 dataModel.getValueAt(row,
843 convertColumnIndexToModel(column)),
844 isSelected,
845 false, // hasFocus
846 row, column);
851 * Get the value of the {@link #autoCreateColumnsFromModel} property.
853 * @return The current value of the property
855 public boolean getAutoCreateColumnsFromModel()
857 return autoCreateColumnsFromModel;
861 * Get the value of the {@link #autoResizeMode} property.
863 * @return The current value of the property
865 public int getAutoResizeMode()
867 return autoResizeMode;
871 * Get the value of the {@link #rowHeight} property.
873 * @return The current value of the property
875 public int getRowHeight()
877 return rowHeight;
881 * Get the value of the {@link #rowMargin} property.
883 * @return The current value of the property
885 public int getRowMargin()
887 return rowMargin;
891 * Get the value of the {@link #rowSelectionAllowed} property.
893 * @return The current value of the property
895 public boolean getRowSelectionAllowed()
897 return rowSelectionAllowed;
901 * Get the value of the {@link #cellSelectionEnabled} property.
903 * @return The current value of the property
905 public boolean getCellSelectionEnabled()
907 return getColumnSelectionAllowed() && getRowSelectionAllowed();
911 * Get the value of the {@link #dataModel} property.
913 * @return The current value of the property
915 public TableModel getModel()
917 return dataModel;
921 * Get the value of the {@link #columnCount} property by
922 * delegation to the @{link #columnModel} field.
924 * @return The current value of the columnCount property
926 public int getColumnCount()
928 return columnModel.getColumnCount();
932 * Get the value of the {@link #rowCount} property by
933 * delegation to the @{link #dataModel} field.
935 * @return The current value of the rowCount property
937 public int getRowCount()
939 return dataModel.getRowCount();
943 * Get the value of the {@link #columnModel} property.
945 * @return The current value of the property
947 public TableColumnModel getColumnModel()
949 return columnModel;
953 * Get the value of the {@link #selectedColumn} property by
954 * delegation to the @{link #columnModel} field.
956 * @return The current value of the selectedColumn property
958 public int getSelectedColumn()
960 return columnModel.getSelectionModel().getMinSelectionIndex();
963 private static int countSelections(ListSelectionModel lsm)
965 int lo = lsm.getMinSelectionIndex();
966 int hi = lsm.getMaxSelectionIndex();
967 int sum = 0;
968 if (lo != -1 && hi != -1)
970 switch (lsm.getSelectionMode())
972 case ListSelectionModel.SINGLE_SELECTION:
973 sum = 1;
974 break;
976 case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
977 sum = hi - lo + 1;
978 break;
980 case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
981 for (int i = lo; i <= hi; ++i)
982 if (lsm.isSelectedIndex(i))
983 ++sum;
984 break;
987 return sum;
990 private static int[] getSelections(ListSelectionModel lsm)
992 int sz = countSelections(lsm);
993 int [] ret = new int[sz];
995 int lo = lsm.getMinSelectionIndex();
996 int hi = lsm.getMaxSelectionIndex();
997 int j = 0;
998 java.util.ArrayList ls = new java.util.ArrayList();
999 if (lo != -1 && hi != -1)
1001 switch (lsm.getSelectionMode())
1003 case ListSelectionModel.SINGLE_SELECTION:
1004 ret[0] = lo;
1005 break;
1007 case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
1008 for (int i = lo; i <= hi; ++i)
1009 ret[j++] = i;
1010 break;
1012 case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
1013 for (int i = lo; i <= hi; ++i)
1014 if (lsm.isSelectedIndex(i))
1015 ret[j++] = i;
1016 break;
1019 return ret;
1023 * Get the value of the {@link #selectedColumnCount} property by
1024 * delegation to the @{link #columnModel} field.
1026 * @return The current value of the selectedColumnCount property
1028 public int getSelectedColumnCount()
1030 return countSelections(columnModel.getSelectionModel());
1034 * Get the value of the {@link #selectedColumns} property by
1035 * delegation to the @{link #columnModel} field.
1037 * @return The current value of the selectedColumns property
1039 public int[] getSelectedColumns()
1041 return getSelections(columnModel.getSelectionModel());
1045 * Get the value of the {@link #columnSelectionAllowed} property.
1047 * @return The current value of the columnSelectionAllowed property
1049 public boolean getColumnSelectionAllowed()
1051 return getColumnModel().getColumnSelectionAllowed();
1055 * Get the value of the {@link #selectedRowCount} property by
1056 * delegation to the @{link #selectionModel} field.
1058 * @return The current value of the selectedRowCount property
1060 public int getSelectedRowCount()
1062 return countSelections(selectionModel);
1066 * Get the value of the {@link #selectedRows} property by
1067 * delegation to the @{link #selectionModel} field.
1069 * @return The current value of the selectedRows property
1071 public int[] getSelectedRows()
1073 return getSelections(selectionModel);
1077 * Get the value of the {@link #accessibleContext} property.
1079 * @return The current value of the property
1081 public AccessibleContext getAccessibleContext()
1083 return accessibleContext;
1087 * Get the value of the {@link #cellEditor} property.
1089 * @return The current value of the property
1091 public TableCellEditor getCellEditor()
1093 return cellEditor;
1097 * Get the value of the {@link #dragEnabled} property.
1099 * @return The current value of the property
1101 public boolean getDragEnabled()
1103 return dragEnabled;
1107 * Get the value of the {@link #gridColor} property.
1109 * @return The current value of the property
1111 public Color getGridColor()
1113 return gridColor;
1117 * Get the value of the {@link #intercellSpacing} property.
1119 * @return The current value of the property
1121 public Dimension getIntercellSpacing()
1123 return new Dimension(columnModel.getColumnMargin(), rowMargin);
1127 * Get the value of the {@link #preferredViewportSize} property.
1129 * @return The current value of the property
1131 public Dimension getPreferredScrollableViewportSize()
1133 return preferredViewportSize;
1137 * Get the value of the {@link #selectionBackground} property.
1139 * @return The current value of the property
1141 public Color getSelectionBackground()
1143 return selectionBackground;
1147 * Get the value of the {@link #selectionForeground} property.
1149 * @return The current value of the property
1151 public Color getSelectionForeground()
1153 return selectionForeground;
1157 * Get the value of the {@link #showHorizontalLines} property.
1159 * @return The current value of the property
1161 public boolean getShowHorizontalLines()
1163 return showHorizontalLines;
1167 * Get the value of the {@link #showVerticalLines} property.
1169 * @return The current value of the property
1171 public boolean getShowVerticalLines()
1173 return showVerticalLines;
1177 * Get the value of the {@link #tableHeader} property.
1179 * @return The current value of the property
1181 public JTableHeader getTableHeader()
1183 return tableHeader;
1187 * Removes specified column from displayable columns of this table.
1189 * @param column column to removed
1191 public void removeColumn(TableColumn column)
1193 columnModel.removeColumn(column);
1197 * Moves column at the specified index to new given location.
1199 * @param column index of the column to move
1200 * @param targetColumn index specifying new location of the column
1202 public void moveColumn(int column,int targetColumn)
1204 columnModel.moveColumn(column, targetColumn);
1208 * Set the value of the {@link #autoCreateColumnsFromModel} property.
1210 * @param a The new value of the autoCreateColumnsFromModel property
1212 public void setAutoCreateColumnsFromModel(boolean a)
1214 autoCreateColumnsFromModel = a;
1218 * Set the value of the {@link #autoResizeMode} property.
1220 * @param a The new value of the autoResizeMode property
1222 public void setAutoResizeMode(int a)
1224 autoResizeMode = a;
1225 revalidate();
1226 repaint();
1230 * Set the value of the {@link #rowHeight} property.
1232 * @param r The new value of the rowHeight property
1234 public void setRowHeight(int r)
1236 if (rowHeight < 1)
1237 throw new IllegalArgumentException();
1239 rowHeight = r;
1240 revalidate();
1241 repaint();
1245 * Set the value of the {@link #rowMargin} property.
1247 * @param r The new value of the rowMargin property
1249 public void setRowMargin(int r)
1251 rowMargin = r;
1252 revalidate();
1253 repaint();
1257 * Set the value of the {@link #rowSelectionAllowed} property.
1259 * @param r The new value of the rowSelectionAllowed property
1261 public void setRowSelectionAllowed(boolean r)
1263 rowSelectionAllowed = r;
1264 repaint();
1268 * Set the value of the {@link #cellSelectionEnabled} property.
1270 * @param c The new value of the cellSelectionEnabled property
1272 public void setCellSelectionEnabled(boolean c)
1274 setColumnSelectionAllowed(c);
1275 setRowSelectionAllowed(c);
1276 // for backward-compatibility sake:
1277 cellSelectionEnabled = true;
1281 * <p>Set the value of the {@link #dataModel} property.</p>
1283 * <p>Unregister <code>this</code> as a {@link TableModelListener} from
1284 * previous {@link #dataModel} and register it with new parameter
1285 * <code>m</code>.</p>
1287 * @param m The new value of the model property
1289 public void setModel(TableModel m)
1291 // Throw exception is m is null.
1292 if (m == null)
1293 throw new IllegalArgumentException();
1295 // Don't do anything if setting the current model again.
1296 if (dataModel == m)
1297 return;
1299 // Remove table as TableModelListener from old model.
1300 if (dataModel != null)
1301 dataModel.removeTableModelListener(this);
1303 if (m != null)
1305 // Set property.
1306 dataModel = m;
1308 // Add table as TableModelListener to new model.
1309 dataModel.addTableModelListener(this);
1311 // Automatically create columns.
1312 if (autoCreateColumnsFromModel)
1313 createColumnsFromModel();
1316 // Repaint table.
1317 revalidate();
1318 repaint();
1322 * <p>Set the value of the {@link #columnModel} property.</p>
1324 * <p>Unregister <code>this</code> as a {@link TableColumnModelListener}
1325 * from previous {@link #columnModel} and register it with new parameter
1326 * <code>c</code>.</p>
1328 * @param c The new value of the columnModel property
1330 public void setColumnModel(TableColumnModel c)
1332 if (c == null)
1333 throw new IllegalArgumentException();
1334 TableColumnModel tmp = columnModel;
1335 if (tmp != null)
1336 tmp.removeColumnModelListener(this);
1337 if (c != null)
1338 c.addColumnModelListener(this);
1339 columnModel = c;
1340 if (dataModel != null && columnModel != null)
1342 int ncols = getColumnCount();
1343 for (int i = 0; i < ncols; ++i)
1344 columnModel.getColumn(i).setHeaderValue(dataModel.getColumnName(i));
1346 revalidate();
1347 repaint();
1351 * Set the value of the {@link #columnSelectionAllowed} property.
1353 * @param c The new value of the property
1355 public void setColumnSelectionAllowed(boolean c)
1357 getColumnModel().setColumnSelectionAllowed(c);
1358 repaint();
1362 * <p>Set the value of the {@link #selectionModel} property.</p>
1364 * <p>Unregister <code>this</code> as a {@link ListSelectionListener}
1365 * from previous {@link #selectionModel} and register it with new
1366 * parameter <code>s</code>.</p>
1368 * @param s The new value of the selectionModel property
1370 public void setSelectionModel(ListSelectionModel s)
1372 if (s == null)
1373 throw new IllegalArgumentException();
1374 ListSelectionModel tmp = selectionModel;
1375 if (tmp != null)
1376 tmp.removeListSelectionListener(this);
1377 if (s != null)
1378 s.addListSelectionListener(this);
1379 selectionModel = s;
1383 * Set the value of the {@link #selectionMode} property by
1384 * delegation to the {@link #selectionModel} field. The same selection
1385 * mode is set for row and column selection models.
1387 * @param s The new value of the property
1389 public void setSelectionMode(int s)
1391 selectionModel.setSelectionMode(s);
1392 columnModel.getSelectionModel().setSelectionMode(s);
1394 repaint();
1398 * <p>Set the value of the {@link #cellEditor} property.</p>
1400 * <p>Unregister <code>this</code> as a {@link CellEditorListener} from
1401 * previous {@link #cellEditor} and register it with new parameter
1402 * <code>c</code>.</p>
1404 * @param c The new value of the cellEditor property
1406 public void setCellEditor(TableCellEditor c)
1408 TableCellEditor tmp = cellEditor;
1409 if (tmp != null)
1410 tmp.removeCellEditorListener(this);
1411 if (c != null)
1412 c.addCellEditorListener(this);
1413 cellEditor = c;
1417 * Set the value of the {@link #dragEnabled} property.
1419 * @param d The new value of the dragEnabled property
1421 public void setDragEnabled(boolean d)
1423 dragEnabled = d;
1427 * Set the value of the {@link #gridColor} property.
1429 * @param g The new value of the gridColor property
1431 public void setGridColor(Color g)
1433 gridColor = g;
1434 repaint();
1438 * Set the value of the {@link #intercellSpacing} property.
1440 * @param i The new value of the intercellSpacing property
1442 public void setIntercellSpacing(Dimension i)
1444 rowMargin = i.height;
1445 columnModel.setColumnMargin(i.width);
1446 repaint();
1450 * Set the value of the {@link #preferredViewportSize} property.
1452 * @param p The new value of the preferredViewportSize property
1454 public void setPreferredScrollableViewportSize(Dimension p)
1456 preferredViewportSize = p;
1457 revalidate();
1458 repaint();
1462 * <p>Set the value of the {@link #selectionBackground} property.</p>
1464 * <p>Fire a PropertyChangeEvent with name {@link
1465 * #SELECTION_BACKGROUND_CHANGED_PROPERTY} to registered listeners, if
1466 * selectionBackground changed.</p>
1468 * @param s The new value of the selectionBackground property
1470 public void setSelectionBackground(Color s)
1472 Color tmp = selectionBackground;
1473 selectionBackground = s;
1474 if (((tmp == null && s != null)
1475 || (s == null && tmp != null)
1476 || (tmp != null && s != null && !tmp.equals(s))))
1477 firePropertyChange(SELECTION_BACKGROUND_CHANGED_PROPERTY, tmp, s);
1478 repaint();
1482 * <p>Set the value of the {@link #selectionForeground} property.</p>
1484 * <p>Fire a PropertyChangeEvent with name {@link
1485 * SELECTION_FOREGROUND_CHANGED_PROPERTY} to registered listeners, if
1486 * selectionForeground changed.</p>
1488 * @param s The new value of the selectionForeground property
1490 public void setSelectionForeground(Color s)
1492 Color tmp = selectionForeground;
1493 selectionForeground = s;
1494 if (((tmp == null && s != null)
1495 || (s == null && tmp != null)
1496 || (tmp != null && s != null && !tmp.equals(s))))
1497 firePropertyChange(SELECTION_FOREGROUND_CHANGED_PROPERTY, tmp, s);
1498 repaint();
1502 * Set the value of the {@link #showGrid} property.
1504 * @param s The new value of the showGrid property
1506 public void setShowGrid(boolean s)
1508 setShowVerticalLines(s);
1509 setShowHorizontalLines(s);
1513 * Set the value of the {@link #showHorizontalLines} property.
1515 * @param s The new value of the showHorizontalLines property
1517 public void setShowHorizontalLines(boolean s)
1519 showHorizontalLines = s;
1520 repaint();
1524 * Set the value of the {@link #showVerticalLines} property.
1526 * @param s The new value of the showVerticalLines property
1528 public void setShowVerticalLines(boolean s)
1530 showVerticalLines = s;
1531 repaint();
1535 * Set the value of the {@link #tableHeader} property.
1537 * @param t The new value of the tableHeader property
1539 public void setTableHeader(JTableHeader t)
1541 if (tableHeader != null)
1542 tableHeader.setTable(null);
1543 tableHeader = t;
1544 if (tableHeader != null)
1545 tableHeader.setTable(this);
1546 revalidate();
1547 repaint();
1550 protected void configureEnclosingScrollPane()
1552 JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
1553 if (jsp != null && tableHeader != null)
1555 jsp.setColumnHeaderView(tableHeader);
1559 protected void unconfigureEnclosingScrollPane()
1561 JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
1562 if (jsp != null)
1564 jsp.setColumnHeaderView(null);
1569 public void addNotify()
1571 super.addNotify();
1572 configureEnclosingScrollPane();
1575 public void removeNotify()
1577 super.addNotify();
1578 unconfigureEnclosingScrollPane();
1583 * Sun javadocs describe an unusual implementation of
1584 * <code>doLayout</code> which involves some private interfaces. We try
1585 * to implement the same algorithm as is documented, but using the
1586 * columnModel directly. We still use a private helper method, but it has
1587 * a simpler signature.
1590 private void distributeSpill(TableColumn[] cols, int spill)
1592 int MIN = 0;
1593 int MAX = 0;
1594 int PREF = 0;
1596 int[] min = new int[cols.length];
1597 int[] max = new int[cols.length];
1598 int[] pref = new int[cols.length];
1600 for (int i = 0; i < cols.length; ++i)
1602 pref[i] = cols[i].getPreferredWidth();
1603 min[i] = cols[i].getMinWidth();
1604 max[i] = cols[i].getMaxWidth();
1605 PREF += pref[i];
1606 MIN += min[i];
1607 MAX += max[i];
1610 for (int i = 0; i < cols.length; ++i)
1612 int adj = 0;
1613 if (spill > 0)
1614 adj = (spill * (pref[i] - min[i])) / (PREF - MIN);
1615 else
1616 adj = (spill * (max[i] - pref[i])) / (MAX - PREF);
1617 cols[i].setWidth(pref[i] + adj);
1621 public void doLayout()
1623 TableColumn resizingColumn = null;
1625 int ncols = getColumnCount();
1626 if (ncols < 1)
1627 return;
1629 int[] pref = new int[ncols];
1630 int prefSum = 0;
1631 int rCol = -1;
1633 if (tableHeader != null)
1634 resizingColumn = tableHeader.getResizingColumn();
1636 for (int i = 0; i < ncols; ++i)
1638 TableColumn col = columnModel.getColumn(i);
1639 int p = col.getWidth();
1640 pref[i] = p;
1641 prefSum += p;
1642 if (resizingColumn == col)
1643 rCol = i;
1646 int spill = prefSum - getWidth();
1648 if (resizingColumn != null)
1650 TableColumn col;
1651 TableColumn [] cols;
1653 switch (getAutoResizeMode())
1655 case AUTO_RESIZE_LAST_COLUMN:
1656 col = columnModel.getColumn(ncols-1);
1657 col.setWidth(col.getPreferredWidth() + spill);
1658 break;
1660 case AUTO_RESIZE_NEXT_COLUMN:
1661 col = columnModel.getColumn(ncols-1);
1662 col.setWidth(col.getPreferredWidth() + spill);
1663 break;
1665 case AUTO_RESIZE_ALL_COLUMNS:
1666 cols = new TableColumn[ncols];
1667 for (int i = 0; i < ncols; ++i)
1668 cols[i] = columnModel.getColumn(i);
1669 distributeSpill(cols, spill);
1670 break;
1672 case AUTO_RESIZE_SUBSEQUENT_COLUMNS:
1673 cols = new TableColumn[ncols];
1674 for (int i = rCol; i < ncols; ++i)
1675 cols[i] = columnModel.getColumn(i);
1676 distributeSpill(cols, spill);
1677 break;
1679 case AUTO_RESIZE_OFF:
1680 default:
1683 else
1685 TableColumn [] cols = new TableColumn[ncols];
1686 for (int i = 0; i < ncols; ++i)
1687 cols[i] = columnModel.getColumn(i);
1688 distributeSpill(cols, spill);
1693 * @deprecated Replaced by <code>doLayout()</code>
1695 public void sizeColumnsToFit(boolean lastColumnOnly)
1697 doLayout();
1701 * Obsolete since JDK 1.4. Please use <code>doLayout()</code>.
1703 public void sizeColumnsToFit(int resizingColumn)
1705 doLayout();
1708 public String getUIClassID()
1710 return "TableUI";
1714 * This method returns the table's UI delegate.
1716 * @return The table's UI delegate.
1718 public TableUI getUI()
1720 return (TableUI) ui;
1724 * This method sets the table's UI delegate.
1726 * @param ui The table's UI delegate.
1728 public void setUI(TableUI ui)
1730 super.setUI(ui);
1733 public void updateUI()
1735 setUI((TableUI) UIManager.getUI(this));
1736 revalidate();
1737 repaint();
1740 public Class getColumnClass(int column)
1742 return dataModel.getColumnClass(column);
1745 public String getColumnName(int column)
1747 return dataModel.getColumnName(column);
1750 public int getEditingColumn()
1752 return editingColumn;
1755 public void setEditingColumn(int column)
1757 editingColumn = column;
1760 public int getEditingRow()
1762 return editingRow;
1765 public void setEditingRow(int column)
1767 editingRow = column;
1770 public Component getEditorComponent()
1772 return editorComp;
1775 public boolean isEditing()
1777 return editorComp != null;
1780 public void setDefaultEditor(Class columnClass, TableCellEditor editor)
1782 if (editor != null)
1783 defaultEditorsByColumnClass.put(columnClass, editor);
1784 else
1785 defaultEditorsByColumnClass.remove(columnClass);
1788 public void addColumnSelectionInterval(int index0, int index1)
1790 if ((index0 < 0 || index0 > (getColumnCount()-1)
1791 || index1 < 0 || index1 > (getColumnCount()-1)))
1792 throw new IllegalArgumentException("Column index out of range.");
1794 getColumnModel().getSelectionModel().addSelectionInterval(index0, index1);
1797 public void addRowSelectionInterval(int index0, int index1)
1799 if ((index0 < 0 || index0 > (getRowCount()-1)
1800 || index1 < 0 || index1 > (getRowCount()-1)))
1801 throw new IllegalArgumentException("Row index out of range.");
1803 getSelectionModel().addSelectionInterval(index0, index1);
1806 public void setColumnSelectionInterval(int index0, int index1)
1808 if ((index0 < 0 || index0 > (getColumnCount()-1)
1809 || index1 < 0 || index1 > (getColumnCount()-1)))
1810 throw new IllegalArgumentException("Column index out of range.");
1812 getColumnModel().getSelectionModel().setSelectionInterval(index0, index1);
1815 public void setRowSelectionInterval(int index0, int index1)
1817 if ((index0 < 0 || index0 > (getRowCount()-1)
1818 || index1 < 0 || index1 > (getRowCount()-1)))
1819 throw new IllegalArgumentException("Row index out of range.");
1821 getSelectionModel().setSelectionInterval(index0, index1);
1824 public void removeColumnSelectionInterval(int index0, int index1)
1826 if ((index0 < 0 || index0 > (getColumnCount()-1)
1827 || index1 < 0 || index1 > (getColumnCount()-1)))
1828 throw new IllegalArgumentException("Column index out of range.");
1830 getColumnModel().getSelectionModel().removeSelectionInterval(index0, index1);
1833 public void removeRowSelectionInterval(int index0, int index1)
1835 if ((index0 < 0 || index0 > (getRowCount()-1)
1836 || index1 < 0 || index1 > (getRowCount()-1)))
1837 throw new IllegalArgumentException("Row index out of range.");
1839 getSelectionModel().removeSelectionInterval(index0, index1);
1842 public boolean isColumnSelected(int column)
1844 return getColumnModel().getSelectionModel().isSelectedIndex(column);
1847 public boolean isRowSelected(int row)
1849 return getSelectionModel().isSelectedIndex(row);
1852 public boolean isCellSelected(int row, int column)
1854 return isRowSelected(row) && isColumnSelected(column);
1857 public void selectAll()
1859 setColumnSelectionInterval(0, getColumnCount() - 1);
1860 setRowSelectionInterval(0, getRowCount() - 1);
1863 public Object getValueAt(int row, int column)
1865 return dataModel.getValueAt(row, convertColumnIndexToModel(column));
1868 public void setValueAt(Object value, int row, int column)
1870 dataModel.setValueAt(value, row, convertColumnIndexToModel(column));
1873 public TableColumn getColumn(Object identifier)
1875 return columnModel.getColumn(columnModel.getColumnIndex(identifier));