Merge from mainline
[official-gcc.git] / libjava / classpath / javax / swing / JTable.java
blob0875306a0127e00101137aa9ba98c16890ed6da3
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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 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.Cursor;
44 import java.awt.Dimension;
45 import java.awt.Font;
46 import java.awt.FontMetrics;
47 import java.awt.Point;
48 import java.awt.Rectangle;
49 import java.awt.event.ActionEvent;
50 import java.awt.event.ActionListener;
51 import java.awt.event.FocusListener;
52 import java.beans.PropertyChangeEvent;
53 import java.beans.PropertyChangeListener;
54 import java.text.DateFormat;
55 import java.text.NumberFormat;
56 import java.util.Date;
57 import java.util.EventObject;
58 import java.util.Hashtable;
59 import java.util.Locale;
60 import java.util.Vector;
62 import javax.accessibility.Accessible;
63 import javax.accessibility.AccessibleComponent;
64 import javax.accessibility.AccessibleContext;
65 import javax.accessibility.AccessibleExtendedTable;
66 import javax.accessibility.AccessibleRole;
67 import javax.accessibility.AccessibleSelection;
68 import javax.accessibility.AccessibleStateSet;
69 import javax.accessibility.AccessibleTable;
70 import javax.accessibility.AccessibleTableModelChange;
71 import javax.swing.event.CellEditorListener;
72 import javax.swing.event.ChangeEvent;
73 import javax.swing.event.ListSelectionEvent;
74 import javax.swing.event.ListSelectionListener;
75 import javax.swing.event.TableColumnModelEvent;
76 import javax.swing.event.TableColumnModelListener;
77 import javax.swing.event.TableModelEvent;
78 import javax.swing.event.TableModelListener;
79 import javax.swing.plaf.TableUI;
80 import javax.swing.table.DefaultTableCellRenderer;
81 import javax.swing.table.DefaultTableColumnModel;
82 import javax.swing.table.DefaultTableModel;
83 import javax.swing.table.JTableHeader;
84 import javax.swing.table.TableCellEditor;
85 import javax.swing.table.TableCellRenderer;
86 import javax.swing.table.TableColumn;
87 import javax.swing.table.TableColumnModel;
88 import javax.swing.table.TableModel;
89 import javax.swing.text.Caret;
91 public class JTable
92 extends JComponent
93 implements TableModelListener, Scrollable, TableColumnModelListener,
94 ListSelectionListener, CellEditorListener, Accessible
96 /**
97 * Provides accessibility support for <code>JTable</code>.
99 * @author Roman Kennke (kennke@aicas.com)
101 protected class AccessibleJTable
102 extends AccessibleJComponent
103 implements AccessibleSelection, ListSelectionListener, TableModelListener,
104 TableColumnModelListener, CellEditorListener, PropertyChangeListener,
105 AccessibleExtendedTable
109 * Provides accessibility support for table cells.
111 * @author Roman Kennke (kennke@aicas.com)
113 protected class AccessibleJTableCell
114 extends AccessibleContext
115 implements Accessible, AccessibleComponent
119 * The table of this cell.
121 private JTable table;
124 * The row index of this cell.
126 private int row;
129 * The column index of this cell.
131 private int column;
134 * The index of this cell inside the AccessibleJTable parent.
136 private int index;
139 * Creates a new <code>AccessibleJTableCell</code>.
141 * @param t the table
142 * @param r the row
143 * @param c the column
144 * @param i the index of this cell inside the accessible table parent
146 public AccessibleJTableCell(JTable t, int r, int c, int i)
148 table = t;
149 row = r;
150 column = c;
151 index = i;
155 * Returns the accessible row for the table cell.
157 * @return the accessible row for the table cell
159 public AccessibleRole getAccessibleRole()
161 // TODO: What is the role of the table cell?
162 return AccessibleRole.UNKNOWN;
166 * Returns the accessible state set of this accessible table cell.
168 * @return the accessible state set of this accessible table cell
170 public AccessibleStateSet getAccessibleStateSet()
172 // TODO: What state shoiuld be returned here?
173 return new AccessibleStateSet();
177 * Returns the index of this cell in the parent object.
179 * @return the index of this cell in the parent object
181 public int getAccessibleIndexInParent()
183 return index;
187 * Returns the number of children of this object. Table cells cannot have
188 * children, so we return <code>0</code> here.
190 * @return <code>0</code>
192 public int getAccessibleChildrenCount()
194 return 0;
198 * Returns the accessible child at index <code>i</code>. Table cells
199 * don't have children, so we return <code>null</code> here.
201 * @return <code>null</code>
203 public Accessible getAccessibleChild(int i)
205 return null;
209 * Returns the locale setting for this accessible table cell.
211 * @return the locale setting for this accessible table cell
213 public Locale getLocale()
215 // TODO: For now, we return english here. This must be fixed as soon
216 // as we have a localized Swing.
217 return Locale.ENGLISH;
221 * Returns the accessible context of this table cell. Since accessible
222 * table cells are their own accessible context, we return
223 * <code>this</code>.
225 * @return the accessible context of this table cell
227 public AccessibleContext getAccessibleContext()
229 return this;
233 * Returns the background color of this cell.
235 * @return the background color of this cell
237 public Color getBackground()
239 return table.getBackground();
243 * Sets the background of the cell. Since table cells cannot have
244 * individual background colors, this method does nothing. Set the
245 * background directly on the table instead.
247 * @param color not used
249 public void setBackground(Color color)
251 // This method does nothing. See API comments.
255 * Returns the foreground color of the table cell.
257 * @return the foreground color of the table cell
259 public Color getForeground()
261 return table.getForeground();
265 * Sets the foreground of the cell. Since table cells cannot have
266 * individual foreground colors, this method does nothing. Set the
267 * foreground directly on the table instead.
269 * @param color not used
271 public void setForeground(Color color)
273 // This method does nothing. See API comments.
277 * Returns the cursor for this table cell.
279 * @return the cursor for this table cell
281 public Cursor getCursor()
283 return table.getCursor();
287 * Sets the cursor of the cell. Since table cells cannot have
288 * individual cursors, this method does nothing. Set the
289 * cursor directly on the table instead.
291 * @param cursor not used
293 public void setCursor(Cursor cursor)
295 // This method does nothing. See API comments.
299 * Returns the font of the table cell.
301 * @return the font of the table cell
303 public Font getFont()
305 return table.getFont();
309 * Sets the font of the cell. Since table cells cannot have
310 * individual fonts, this method does nothing. Set the
311 * font directly on the table instead.
313 * @param font not used
315 public void setFont(Font font)
317 // This method does nothing. See API comments.
321 * Returns the font metrics for a specified font.
323 * @param font the font for which we return the metrics
325 * @return the font metrics for a specified font
327 public FontMetrics getFontMetrics(Font font)
329 return table.getFontMetrics(font);
333 * Returns <code>true</code> if this table cell is enabled,
334 * <code>false</code> otherwise.
336 * @return <code>true</code> if this table cell is enabled,
337 * <code>false</code> otherwise
339 public boolean isEnabled()
341 return table.isEnabled();
345 * Table cells cannot be disabled or enabled individually, so this method
346 * does nothing. Set the enabled flag on the table itself.
348 * @param b not used here
350 public void setEnabled(boolean b)
352 // This method does nothing. See API comments.
356 * Returns <code>true</code> if this cell is visible, <code>false</code>
357 * otherwise.
359 * @return <code>true</code> if this cell is visible, <code>false</code>
360 * otherwise
362 public boolean isVisible()
364 return table.isVisible();
368 * The visibility cannot be set on individual table cells, so this method
369 * does nothing. Set the visibility on the table itself.
371 * @param b not used
373 public void setVisible(boolean b)
375 // This method does nothing. See API comments.
379 * Returns <code>true</code> if this table cell is currently showing on
380 * screen.
382 * @return <code>true</code> if this table cell is currently showing on
383 * screen
385 public boolean isShowing()
387 return table.isShowing();
391 * Returns <code>true</code> if this table cell contains the location
392 * at <code>point</code>, <code>false</code> otherwise.
393 * <code>point</code> is interpreted as relative to the coordinate system
394 * of the table cell.
396 * @return <code>true</code> if this table cell contains the location
397 * at <code>point</code>, <code>false</code> otherwise
399 public boolean contains(Point point)
401 Rectangle cellRect = table.getCellRect(row, column, true);
402 cellRect.x = 0;
403 cellRect.y = 0;
404 return cellRect.contains(point);
408 * Returns the screen location of the table cell.
410 * @return the screen location of the table cell
412 public Point getLocationOnScreen()
414 Point tableLoc = table.getLocationOnScreen();
415 Rectangle cellRect = table.getCellRect(row, column, true);
416 tableLoc.x += cellRect.x;
417 tableLoc.y += cellRect.y;
418 return tableLoc;
422 * Returns the location of this cell relative to the table's bounds.
424 * @return the location of this cell relative to the table's bounds
426 public Point getLocation()
428 Rectangle cellRect = table.getCellRect(row, column, true);
429 return new Point(cellRect.x, cellRect.y);
433 * The location of the table cells cannot be manipulated directly, so
434 * this method does nothing.
436 * @param point not used
438 public void setLocation(Point point)
440 // This method does nothing. See API comments.
444 * Returns the bounds of the cell relative to its table.
446 * @return the bounds of the cell relative to its table
448 public Rectangle getBounds()
450 return table.getCellRect(row, column, true);
454 * The bounds of the table cells cannot be manipulated directly, so
455 * this method does nothing.
457 * @param rectangle not used
459 public void setBounds(Rectangle rectangle)
461 // This method does nothing. See API comments.
465 * Returns the size of the table cell.
467 * @return the size of the table cell
469 public Dimension getSize()
471 Rectangle cellRect = table.getCellRect(row, column, true);
472 return new Dimension(cellRect.width, cellRect.height);
476 * The size cannot be set on table cells directly, so this method does
477 * nothing.
479 * @param dimension not used
481 public void setSize(Dimension dimension)
483 // This method does nothing. See API comments.
487 * Table cells have no children, so we return <code>null</code> here.
489 * @return <code>null</code>
491 public Accessible getAccessibleAt(Point point)
493 return null;
497 * Returns <code>true</code> if this table cell is focus traversable,
498 * <code>false</code> otherwise.
500 * @return <code>true</code> if this table cell is focus traversable,
501 * <code>false</code> otherwise
503 public boolean isFocusTraversable()
505 return table.isFocusable();
509 * Requests that this table cell gets the keyboard focus.
511 public void requestFocus()
513 // We first set the selection models' lead selection to this cell.
514 table.getColumnModel().getSelectionModel()
515 .setLeadSelectionIndex(column);
516 table.getSelectionModel().setLeadSelectionIndex(row);
517 // Now we request that the table receives focus.
518 table.requestFocus();
522 * Adds a focus listener to this cell. The focus listener is really
523 * added to the table, so there is no way to find out when an individual
524 * cell changes the focus.
526 * @param listener the focus listener to add
528 public void addFocusListener(FocusListener listener)
530 table.addFocusListener(listener);
534 * Removes a focus listener from the cell. The focus listener is really
535 * removed from the table.
537 * @param listener the listener to remove
539 public void removeFocusListener(FocusListener listener)
541 table.removeFocusListener(listener);
546 protected class AccessibleJTableModelChange
547 implements AccessibleTableModelChange
549 protected int type;
550 protected int firstRow;
551 protected int lastRow;
552 protected int firstColumn;
553 protected int lastColumn;
555 protected AccessibleJTableModelChange(int type, int firstRow,
556 int lastRow, int firstColumn,
557 int lastColumn)
559 this.type = type;
560 this.firstRow = firstRow;
561 this.lastRow = lastRow;
562 this.firstColumn = firstColumn;
563 this.lastColumn = lastColumn;
566 public int getType()
568 return type;
571 public int getFirstRow()
573 return firstRow;
576 public int getLastRow()
578 return lastRow;
581 public int getFirstColumn()
583 return firstColumn;
586 public int getLastColumn()
588 return lastColumn;
593 * Creates a new <code>AccessibleJTable</code>.
595 * @since JDK1.5
597 protected AccessibleJTable()
599 getModel().addTableModelListener(this);
600 getSelectionModel().addListSelectionListener(this);
601 getColumnModel().addColumnModelListener(this);
602 getCellEditor().addCellEditorListener(this);
606 * Returns the number of selected items in this table.
608 public int getAccessibleSelectionCount()
610 return getSelectedColumnCount();
613 public Accessible getAccessibleSelection(int i)
615 // TODO Auto-generated method stub
616 return null;
619 public boolean isAccessibleChildSelected(int i)
621 // TODO Auto-generated method stub
622 return false;
625 public void addAccessibleSelection(int i)
627 // TODO Auto-generated method stub
631 public void removeAccessibleSelection(int i)
633 // TODO Auto-generated method stub
637 public void clearAccessibleSelection()
639 // TODO Auto-generated method stub
643 public void selectAllAccessibleSelection()
645 // TODO Auto-generated method stub
649 public void valueChanged(ListSelectionEvent event)
651 // TODO Auto-generated method stub
656 * Receives notification when the table model changes. Depending on the
657 * type of change, this method calls {@link #tableRowsInserted} or
658 * {@link #tableRowsDeleted}.
660 * @param event the table model event
662 public void tableChanged(TableModelEvent event)
664 switch (event.getType())
666 case TableModelEvent.INSERT:
667 tableRowsInserted(event);
668 break;
669 case TableModelEvent.DELETE:
670 tableRowsDeleted(event);
671 break;
676 * Receives notification when one or more rows have been inserted into the
677 * table.
679 * @param event the table model event
681 public void tableRowsInserted(TableModelEvent event)
683 // TODO: What to do here, if anything? This might be a hook method for
684 // subclasses...
688 * Receives notification when one or more rows have been deleted from the
689 * table.
691 * @param event the table model event
693 public void tableRowsDeleted(TableModelEvent event)
695 // TODO: What to do here, if anything? This might be a hook method for
696 // subclasses...
699 public void columnAdded(TableColumnModelEvent event)
701 // TODO Auto-generated method stub
705 public void columnMarginChanged(ChangeEvent event)
707 // TODO Auto-generated method stub
711 public void columnMoved(TableColumnModelEvent event)
713 // TODO Auto-generated method stub
717 public void columnRemoved(TableColumnModelEvent event)
719 // TODO Auto-generated method stub
723 public void columnSelectionChanged(ListSelectionEvent event)
725 // TODO Auto-generated method stub
729 public void editingCanceled(ChangeEvent event)
731 // TODO Auto-generated method stub
735 public void editingStopped(ChangeEvent event)
737 // TODO Auto-generated method stub
742 * Receives notification when any of the JTable's properties changes. This
743 * is used to replace the listeners on the table's model, selection model,
744 * column model and cell editor.
746 * @param e the property change event
748 public void propertyChange(PropertyChangeEvent e)
750 String propName = e.getPropertyName();
751 if (propName.equals("tableModel"))
753 TableModel oldModel = (TableModel) e.getOldValue();
754 oldModel.removeTableModelListener(this);
755 TableModel newModel = (TableModel) e.getNewValue();
756 newModel.addTableModelListener(this);
758 else if (propName.equals("columnModel"))
760 TableColumnModel oldModel = (TableColumnModel) e.getOldValue();
761 oldModel.removeColumnModelListener(this);
762 TableColumnModel newModel = (TableColumnModel) e.getNewValue();
763 newModel.addColumnModelListener(this);
765 else if (propName.equals("selectionModel"))
767 ListSelectionModel oldModel = (ListSelectionModel) e.getOldValue();
768 oldModel.removeListSelectionListener(this);
769 ListSelectionModel newModel = (ListSelectionModel) e.getNewValue();
770 newModel.addListSelectionListener(this);
772 else if (propName.equals("cellEditor"))
774 CellEditor oldEd = (CellEditor) e.getOldValue();
775 oldEd.removeCellEditorListener(this);
776 CellEditor newEd = (CellEditor) e.getNewValue();
777 newEd.addCellEditorListener(this);
781 public int getAccessibleRow(int index)
783 // TODO Auto-generated method stub
784 return 0;
787 public int getAccessibleColumn(int index)
789 // TODO Auto-generated method stub
790 return 0;
793 public int getAccessibleIndex(int r, int c)
795 // TODO Auto-generated method stub
796 return 0;
799 public Accessible getAccessibleCaption()
801 // TODO Auto-generated method stub
802 return null;
805 public void setAccessibleCaption(Accessible caption)
807 // TODO Auto-generated method stub
811 public Accessible getAccessibleSummary()
813 // TODO Auto-generated method stub
814 return null;
817 public void setAccessibleSummary(Accessible summary)
819 // TODO Auto-generated method stub
823 public int getAccessibleRowCount()
825 // TODO Auto-generated method stub
826 return 0;
829 public int getAccessibleColumnCount()
831 // TODO Auto-generated method stub
832 return 0;
835 public Accessible getAccessibleAt(int r, int c)
837 // TODO Auto-generated method stub
838 return null;
841 public int getAccessibleRowExtentAt(int r, int c)
843 // TODO Auto-generated method stub
844 return 0;
847 public int getAccessibleColumnExtentAt(int r, int c)
849 // TODO Auto-generated method stub
850 return 0;
853 public AccessibleTable getAccessibleRowHeader()
855 // TODO Auto-generated method stub
856 return null;
859 public void setAccessibleRowHeader(AccessibleTable header)
861 // TODO Auto-generated method stub
865 public AccessibleTable getAccessibleColumnHeader()
867 // TODO Auto-generated method stub
868 return null;
871 public void setAccessibleColumnHeader(AccessibleTable header)
873 // TODO Auto-generated method stub
877 public Accessible getAccessibleRowDescription(int r)
879 // TODO Auto-generated method stub
880 return null;
883 public void setAccessibleRowDescription(int r, Accessible description)
885 // TODO Auto-generated method stub
889 public Accessible getAccessibleColumnDescription(int c)
891 // TODO Auto-generated method stub
892 return null;
895 public void setAccessibleColumnDescription(int c, Accessible description)
897 // TODO Auto-generated method stub
901 public boolean isAccessibleSelected(int r, int c)
903 // TODO Auto-generated method stub
904 return false;
907 public boolean isAccessibleRowSelected(int r)
909 // TODO Auto-generated method stub
910 return false;
913 public boolean isAccessibleColumnSelected(int c)
915 // TODO Auto-generated method stub
916 return false;
919 public int[] getSelectedAccessibleRows()
921 // TODO Auto-generated method stub
922 return null;
925 public int[] getSelectedAccessibleColumns()
927 // TODO Auto-generated method stub
928 return null;
932 * Returns the accessible row at the specified index.
934 * @param index the index for which to query the row
936 * @return the row number at the specified table index
938 public int getAccessibleRowAtIndex(int index)
940 // TODO: Back this up by a Mauve test and update API docs accordingly.
941 return index / getColumnCount();
945 * Returns the accessible column at the specified index.
947 * @param index the index for which to query the column
949 * @return the column number at the specified table index
951 public int getAccessibleColumnAtIndex(int index)
953 // TODO: Back this up by a Mauve test and update API docs accordingly.
954 return index % getColumnCount();
958 * Returns the accessible child index at the specified column and row.
960 * @param row the row
961 * @param column the column
963 * @return the index of the accessible child at the specified row and
964 * column
966 public int getAccessibleIndexAt(int row, int column)
968 // TODO: Back this up by a Mauve test and update API docs accordingly.
969 return row * getColumnCount() + column;
973 * Handles property changes from the <code>TableColumn</code>s of this
974 * <code>JTable</code>.
976 * More specifically, this triggers a {@link #revalidate()} call if the
977 * preferredWidth of one of the observed columns changes.
979 class TableColumnPropertyChangeHandler implements PropertyChangeListener
982 * Receives notification that a property of the observed TableColumns
983 * has changed.
985 * @param ev the property change event
987 public void propertyChange(PropertyChangeEvent ev)
989 if (ev.getPropertyName().equals("preferredWidth"))
991 JTableHeader header = getTableHeader();
992 if (header != null)
994 TableColumn col = (TableColumn) ev.getSource();
995 header.setResizingColumn(col);
996 doLayout();
997 header.setResizingColumn(null);
1004 * A cell renderer for boolean values.
1006 private class BooleanCellRenderer
1007 extends DefaultTableCellRenderer
1011 * The CheckBox that is used for rendering.
1013 private JCheckBox checkBox = new JCheckBox();
1016 * Returns the component that is used for rendering the value.
1018 * @param table the JTable
1019 * @param value the value of the object
1020 * @param isSelected is the cell selected?
1021 * @param hasFocus has the cell the focus?
1022 * @param row the row to render
1023 * @param column the cell to render
1025 * @return this component (the default table cell renderer)
1027 public Component getTableCellRendererComponent(JTable table, Object value,
1028 boolean isSelected,
1029 boolean hasFocus, int row,
1030 int column)
1032 Boolean boolValue = (Boolean) value;
1033 checkBox.setSelected(boolValue.booleanValue());
1034 return checkBox;
1039 * A cell renderer for Date values.
1041 private class DateCellRenderer
1042 extends DefaultTableCellRenderer
1045 * Returns the component that is used for rendering the value.
1047 * @param table the JTable
1048 * @param value the value of the object
1049 * @param isSelected is the cell selected?
1050 * @param hasFocus has the cell the focus?
1051 * @param row the row to render
1052 * @param column the cell to render
1054 * @return this component (the default table cell renderer)
1056 public Component getTableCellRendererComponent(JTable table, Object value,
1057 boolean isSelected,
1058 boolean hasFocus, int row,
1059 int column)
1061 super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1062 row, column);
1063 if (value instanceof Date)
1065 Date dateValue = (Date) value;
1066 DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
1067 setText(df.format(dateValue));
1069 return this;
1074 * A cell renderer for Double values.
1076 private class DoubleCellRenderer
1077 extends DefaultTableCellRenderer
1080 * Creates a new instance of NumberCellRenderer.
1082 public DoubleCellRenderer()
1084 setHorizontalAlignment(JLabel.RIGHT);
1088 * Returns the component that is used for rendering the value.
1090 * @param table the JTable
1091 * @param value the value of the object
1092 * @param isSelected is the cell selected?
1093 * @param hasFocus has the cell the focus?
1094 * @param row the row to render
1095 * @param column the cell to render
1097 * @return this component (the default table cell renderer)
1099 public Component getTableCellRendererComponent(JTable table, Object value,
1100 boolean isSelected,
1101 boolean hasFocus, int row,
1102 int column)
1104 super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1105 row, column);
1106 if (value instanceof Double)
1108 Double doubleValue = (Double) value;
1109 NumberFormat nf = NumberFormat.getInstance();
1110 setText(nf.format(doubleValue.doubleValue()));
1112 return this;
1117 * A cell renderer for Float values.
1119 private class FloatCellRenderer
1120 extends DefaultTableCellRenderer
1123 * Creates a new instance of NumberCellRenderer.
1125 public FloatCellRenderer()
1127 setHorizontalAlignment(JLabel.RIGHT);
1131 * Returns the component that is used for rendering the value.
1133 * @param table the JTable
1134 * @param value the value of the object
1135 * @param isSelected is the cell selected?
1136 * @param hasFocus has the cell the focus?
1137 * @param row the row to render
1138 * @param column the cell to render
1140 * @return this component (the default table cell renderer)
1142 public Component getTableCellRendererComponent(JTable table, Object value,
1143 boolean isSelected,
1144 boolean hasFocus, int row,
1145 int column)
1147 super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1148 row, column);
1149 if (value instanceof Float)
1151 Float floatValue = (Float) value;
1152 NumberFormat nf = NumberFormat.getInstance();
1153 setText(nf.format(floatValue.floatValue()));
1155 return this;
1160 * A cell renderer for Number values.
1162 private class NumberCellRenderer
1163 extends DefaultTableCellRenderer
1166 * Creates a new instance of NumberCellRenderer.
1168 public NumberCellRenderer()
1170 setHorizontalAlignment(JLabel.RIGHT);
1175 * A cell renderer for Icon values.
1177 private class IconCellRenderer
1178 extends DefaultTableCellRenderer
1181 * Returns the component that is used for rendering the value.
1183 * @param table the JTable
1184 * @param value the value of the object
1185 * @param isSelected is the cell selected?
1186 * @param hasFocus has the cell the focus?
1187 * @param row the row to render
1188 * @param column the cell to render
1190 * @return this component (the default table cell renderer)
1192 public Component getTableCellRendererComponent(JTable table, Object value,
1193 boolean isSelected,
1194 boolean hasFocus, int row,
1195 int column)
1197 super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1198 row, column);
1199 if (value instanceof Icon)
1201 Icon iconValue = (Icon) value;
1202 setIcon(iconValue);
1204 return this;
1208 private static final long serialVersionUID = 3876025080382781659L;
1212 * When resizing columns, do not automatically change any columns. In this
1213 * case the table should be enclosed in a {@link JScrollPane} in order to
1214 * accomodate cases in which the table size exceeds its visible area.
1216 public static final int AUTO_RESIZE_OFF = 0;
1219 * When resizing column <code>i</code>, automatically change only the
1220 * single column <code>i+1</code> to provide or absorb excess space
1221 * requirements.
1223 public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
1226 * When resizing column <code>i</code> in a table of <code>n</code>
1227 * columns, automatically change all columns in the range <code>[i+1,
1228 * n)</code>, uniformly, to provide or absorb excess space requirements.
1230 public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
1233 * When resizing column <code>i</code> in a table of <code>n</code>
1234 * columns, automatically change all columns in the range <code>[0,
1235 * n)</code> (with the exception of column i) uniformly, to provide or
1236 * absorb excess space requirements.
1238 public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
1241 * When resizing column <code>i</code> in a table of <code>n</code>
1242 * columns, automatically change column <code>n-1</code> (the last column
1243 * in the table) to provide or absorb excess space requirements.
1245 public static final int AUTO_RESIZE_LAST_COLUMN = 3;
1249 * A table mapping {@link java.lang.Class} objects to
1250 * {@link TableCellEditor} objects. This table is consulted by the
1251 * FIXME
1253 protected Hashtable defaultEditorsByColumnClass;
1256 * A table mapping {@link java.lang.Class} objects to
1257 * {@link TableCellEditor} objects. This table is consulted by the
1258 * FIXME
1260 protected Hashtable defaultRenderersByColumnClass;
1263 * The column that is edited, -1 if the table is not edited currently.
1265 protected int editingColumn;
1268 * The row that is edited, -1 if the table is not edited currently.
1270 protected int editingRow;
1273 * The component that is used for editing.
1274 * <code>null</code> if the table is not editing currently.
1277 protected transient Component editorComp;
1281 * Whether or not the table should automatically compute a matching
1282 * {@link TableColumnModel} and assign it to the {@link #columnModel}
1283 * property when the {@link #dataModel} property is changed.
1285 * @see #setModel(TableModel)
1286 * @see #createDefaultColumnsFromModel()
1287 * @see #setColumnModel(TableColumnModel)
1288 * @see #setAutoCreateColumnsFromModel(boolean)
1289 * @see #getAutoCreateColumnsFromModel()
1291 protected boolean autoCreateColumnsFromModel;
1294 * A numeric code specifying the resizing behavior of the table. Must be
1295 * one of {@link #AUTO_RESIZE_ALL_COLUMNS} (the default), {@link
1296 * #AUTO_RESIZE_LAST_COLUMN}, {@link #AUTO_RESIZE_NEXT_COLUMN}, {@link
1297 * #AUTO_RESIZE_SUBSEQUENT_COLUMNS}, or {@link #AUTO_RESIZE_OFF}.
1299 * @see #doLayout()
1300 * @see #setAutoResizeMode(int)
1301 * @see #getAutoResizeMode()
1303 protected int autoResizeMode;
1306 * The height in pixels of any row of the table. All rows in a table are
1307 * of uniform height. This differs from column width, which varies on a
1308 * per-column basis, and is stored in the individual columns of the
1309 * {@link #columnModel}.
1311 * @see #getRowHeight()
1312 * @see #setRowHeight(int)
1313 * @see TableColumn#getWidth()
1314 * @see TableColumn#setWidth(int)
1316 protected int rowHeight;
1319 * The height in pixels of the gap left between any two rows of the table.
1321 * @see #setRowMargin(int)
1322 * @see #getRowHeight()
1323 * @see #getIntercellSpacing()
1324 * @see #setIntercellSpacing(Dimension)
1325 * @see TableColumnModel#getColumnMargin()
1326 * @see TableColumnModel#setColumnMargin(int)
1328 protected int rowMargin;
1331 * Whether or not the table should allow row selection. If the table
1332 * allows both row <em>and</em> column selection, it is said to allow
1333 * "cell selection". Previous versions of the JDK supported cell
1334 * selection as an independent concept, but it is now represented solely
1335 * in terms of simultaneous row and column selection.
1337 * @see TableColumnModel#getColumnSelectionAllowed()
1338 * @see #setRowSelectionAllowed(boolean)
1339 * @see #getRowSelectionAllowed()
1340 * @see #getCellSelectionEnabled()
1341 * @see #setCellSelectionEnabled(boolean)
1343 protected boolean rowSelectionAllowed;
1346 * @deprecated Use {@link #rowSelectionAllowed}, {@link
1347 * #getColumnSelectionAllowed}, or the combined methods {@link
1348 * #getCellSelectionEnabled} and {@link #setCellSelectionEnabled(boolean)}.
1350 protected boolean cellSelectionEnabled;
1353 * The model for data stored in the table. Confusingly, the published API
1354 * requires that this field be called <code>dataModel</code>, despite its
1355 * property name. The table listens to its model as a {@link
1356 * TableModelListener}.
1358 * @see #tableChanged(TableModelEvent)
1359 * @see TableModel#addTableModelListener(TableModelListener)
1361 protected TableModel dataModel;
1364 * <p>A model of various aspects of the columns of the table, <em>not
1365 * including</em> the data stored in them. The {@link TableColumnModel}
1366 * is principally concerned with holding a set of {@link TableColumn}
1367 * objects, each of which describes the display parameters of a column
1368 * and the numeric index of the column from the data model which the
1369 * column is presenting.</p>
1371 * <p>The TableColumnModel also contains a {@link ListSelectionModel} which
1372 * indicates which columns are currently selected. This selection model
1373 * works in combination with the {@link #selectionModel} of the table
1374 * itself to specify a <em>table selection</em>: a combination of row and
1375 * column selections.</p>
1377 * <p>Most application programmers do not need to work with this property
1378 * at all: setting {@link #autoCreateColumnsFromModel} will construct the
1379 * columnModel automatically, and the table acts as a facade for most of
1380 * the interesting properties of the columnModel anyways.</p>
1382 * @see #setColumnModel(TableColumnModel)
1383 * @see #getColumnModel()
1385 protected TableColumnModel columnModel;
1388 * A model of the rows of this table which are currently selected. This
1389 * model is used in combination with the column selection model held as a
1390 * member of the {@link #columnModel} property, to represent the rows and
1391 * columns (or both: cells) of the table which are currently selected.
1393 * @see #rowSelectionAllowed
1394 * @see #setSelectionModel(ListSelectionModel)
1395 * @see #getSelectionModel()
1396 * @see TableColumnModel#getSelectionModel()
1397 * @see ListSelectionModel#addListSelectionListener(ListSelectionListener)
1399 protected ListSelectionModel selectionModel;
1402 * The current cell editor.
1404 protected TableCellEditor cellEditor;
1407 * Whether or not drag-and-drop is enabled on this table.
1409 * @see #setDragEnabled(boolean)
1410 * @see #getDragEnabled()
1412 private boolean dragEnabled;
1415 * The color to paint the grid lines of the table, when either {@link
1416 * #showHorizontalLines} or {@link #showVerticalLines} is set.
1418 * @see #setGridColor(Color)
1419 * @see #getGridColor()
1421 protected Color gridColor;
1424 * The size this table would prefer its viewport assume, if it is
1425 * contained in a {@link JScrollPane}.
1427 * @see #setPreferredScrollableViewportSize(Dimension)
1428 * @see #getPreferredScrollableViewportSize()
1430 protected Dimension preferredViewportSize;
1433 * The color to paint the background of selected cells. Fires a property
1434 * change event with name {@link #SELECTION_BACKGROUND_CHANGED_PROPERTY}
1435 * when its value changes.
1437 * @see #setSelectionBackground(Color)
1438 * @see #getSelectionBackground()
1440 protected Color selectionBackground;
1443 * The name carried in property change events when the {@link
1444 * #selectionBackground} property changes.
1446 private static final String SELECTION_BACKGROUND_CHANGED_PROPERTY = "selectionBackground";
1449 * The color to paint the foreground of selected cells. Fires a property
1450 * change event with name {@link #SELECTION_FOREGROUND_CHANGED_PROPERTY}
1451 * when its value changes.
1453 * @see #setSelectionForeground(Color)
1454 * @see #getSelectionForeground()
1456 protected Color selectionForeground;
1459 * The name carried in property change events when the
1460 * {@link #selectionForeground} property changes.
1462 private static final String SELECTION_FOREGROUND_CHANGED_PROPERTY = "selectionForeground";
1465 * The showHorizontalLines property.
1467 protected boolean showHorizontalLines;
1470 * The showVerticalLines property.
1472 protected boolean showVerticalLines;
1475 * The tableHeader property.
1477 protected JTableHeader tableHeader;
1480 * The row of the cell being edited.
1482 int rowBeingEdited = -1;
1485 * The column of the cell being edited.
1487 int columnBeingEdited = -1;
1490 * The action listener for the editor's Timer.
1492 Timer editorTimer = new EditorUpdateTimer();
1495 * Stores the old value of a cell before it was edited, in case
1496 * editing is cancelled
1498 Object oldCellValue;
1501 * The property handler for this table's columns.
1503 TableColumnPropertyChangeHandler tableColumnPropertyChangeHandler =
1504 new TableColumnPropertyChangeHandler();
1507 * Whether cell editors should receive keyboard focus when the table is
1508 * activated.
1510 private boolean surrendersFocusOnKeystroke = false;
1513 * Creates a new <code>JTable</code> instance.
1515 public JTable ()
1517 this(null, null, null);
1521 * Creates a new <code>JTable</code> instance.
1523 * @param numRows an <code>int</code> value
1524 * @param numColumns an <code>int</code> value
1526 public JTable (int numRows, int numColumns)
1528 this(new DefaultTableModel(numRows, numColumns));
1532 * Creates a new <code>JTable</code> instance.
1534 * @param data an <code>Object[][]</code> value
1535 * @param columnNames an <code>Object[]</code> value
1537 public JTable(Object[][] data, Object[] columnNames)
1539 this(new DefaultTableModel(data, columnNames));
1543 * Creates a new <code>JTable</code> instance.
1545 * @param dm a <code>TableModel</code> value
1547 public JTable (TableModel dm)
1549 this(dm, null, null);
1553 * Creates a new <code>JTable</code> instance.
1555 * @param dm a <code>TableModel</code> value
1556 * @param cm a <code>TableColumnModel</code> value
1558 public JTable (TableModel dm, TableColumnModel cm)
1560 this(dm, cm, null);
1564 * Creates a new <code>JTable</code> instance.
1566 * @param dm a <code>TableModel</code> value
1567 * @param cm a <code>TableColumnModel</code> value
1568 * @param sm a <code>ListSelectionModel</code> value
1570 public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm)
1572 boolean autoCreate = false;
1573 if (cm != null)
1574 setColumnModel(cm);
1575 else
1577 setColumnModel(createDefaultColumnModel());
1578 autoCreate = true;
1580 setSelectionModel(sm == null ? createDefaultSelectionModel() : sm);
1581 setModel(dm == null ? createDefaultDataModel() : dm);
1582 setAutoCreateColumnsFromModel(autoCreate);
1583 initializeLocalVars();
1584 // The following four lines properly set the lead selection indices.
1585 // After this, the UI will handle the lead selection indices.
1586 // FIXME: this should probably not be necessary, if the UI is installed
1587 // before the TableModel is set then the UI will handle things on its
1588 // own, but certain variables need to be set before the UI can be installed
1589 // so we must get the correct order for all the method calls in this
1590 // constructor.
1591 selectionModel.setAnchorSelectionIndex(0);
1592 selectionModel.setLeadSelectionIndex(0);
1593 columnModel.getSelectionModel().setAnchorSelectionIndex(0);
1594 columnModel.getSelectionModel().setLeadSelectionIndex(0);
1595 updateUI();
1598 protected void initializeLocalVars()
1600 setTableHeader(createDefaultTableHeader());
1601 if (autoCreateColumnsFromModel)
1602 createDefaultColumnsFromModel();
1603 this.columnModel.addColumnModelListener(this);
1605 this.defaultRenderersByColumnClass = new Hashtable();
1606 createDefaultRenderers();
1608 this.defaultEditorsByColumnClass = new Hashtable();
1609 createDefaultEditors();
1611 this.autoResizeMode = AUTO_RESIZE_SUBSEQUENT_COLUMNS;
1612 this.rowHeight = 16;
1613 this.rowMargin = 1;
1614 this.rowSelectionAllowed = true;
1615 // this.accessibleContext = new AccessibleJTable();
1616 this.cellEditor = null;
1617 // COMPAT: Both Sun and IBM have drag enabled
1618 this.dragEnabled = true;
1619 this.preferredViewportSize = new Dimension(450,400);
1620 this.showHorizontalLines = true;
1621 this.showVerticalLines = true;
1622 this.editingColumn = -1;
1623 this.editingRow = -1;
1624 setIntercellSpacing(new Dimension(1,1));
1628 * Creates a new <code>JTable</code> instance.
1630 * @param data a <code>Vector</code> value
1631 * @param columnNames a <code>Vector</code> value
1633 public JTable(Vector data, Vector columnNames)
1635 this(new DefaultTableModel(data, columnNames));
1639 * The timer that updates the editor component.
1641 private class EditorUpdateTimer
1642 extends Timer
1643 implements ActionListener
1646 * Creates a new EditorUpdateTimer object with a default delay of 0.5 seconds.
1648 public EditorUpdateTimer()
1650 super(500, null);
1651 addActionListener(this);
1655 * Lets the caret blink and repaints the table.
1657 public void actionPerformed(ActionEvent ev)
1659 Caret c = ((JTextField)JTable.this.editorComp).getCaret();
1660 if (c != null)
1661 c.setVisible(!c.isVisible());
1662 JTable.this.repaint();
1666 * Updates the blink delay according to the current caret.
1668 public void update()
1670 stop();
1671 Caret c = ((JTextField)JTable.this.editorComp).getCaret();
1672 if (c != null)
1674 setDelay(c.getBlinkRate());
1675 if (((JTextField)JTable.this.editorComp).isEditable())
1676 start();
1677 else
1678 c.setVisible(false);
1683 public void addColumn(TableColumn column)
1685 if (column.getHeaderValue() == null)
1687 String name = dataModel.getColumnName(column.getModelIndex());
1688 column.setHeaderValue(name);
1691 columnModel.addColumn(column);
1692 column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
1695 protected void createDefaultEditors()
1697 //FIXME: Create the editor object.
1700 protected void createDefaultRenderers()
1702 setDefaultRenderer(Boolean.class, new BooleanCellRenderer());
1703 setDefaultRenderer(Number.class, new NumberCellRenderer());
1704 setDefaultRenderer(Double.class, new DoubleCellRenderer());
1705 setDefaultRenderer(Double.class, new FloatCellRenderer());
1706 setDefaultRenderer(Date.class, new DateCellRenderer());
1707 setDefaultRenderer(Icon.class, new IconCellRenderer());
1711 * @deprecated 1.0.2, replaced by <code>new JScrollPane(JTable)</code>
1713 public static JScrollPane createScrollPaneForTable(JTable table)
1715 return new JScrollPane(table);
1718 protected TableColumnModel createDefaultColumnModel()
1720 return new DefaultTableColumnModel();
1723 protected TableModel createDefaultDataModel()
1725 return new DefaultTableModel();
1728 protected ListSelectionModel createDefaultSelectionModel()
1730 return new DefaultListSelectionModel();
1733 protected JTableHeader createDefaultTableHeader()
1735 return new JTableHeader(columnModel);
1738 // listener support
1740 public void columnAdded (TableColumnModelEvent event)
1742 revalidate();
1743 repaint();
1746 public void columnMarginChanged (ChangeEvent event)
1748 revalidate();
1749 repaint();
1752 public void columnMoved (TableColumnModelEvent event)
1754 revalidate();
1755 repaint();
1758 public void columnRemoved (TableColumnModelEvent event)
1760 revalidate();
1761 repaint();
1764 public void columnSelectionChanged (ListSelectionEvent event)
1766 repaint();
1769 public void editingCanceled (ChangeEvent event)
1771 if (rowBeingEdited > -1 && columnBeingEdited > -1)
1773 if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField)
1775 remove ((Component)getValueAt(rowBeingEdited, columnBeingEdited));
1776 setValueAt(oldCellValue, rowBeingEdited, columnBeingEdited);
1778 rowBeingEdited = -1;
1779 columnBeingEdited = -1;
1781 editorTimer.stop();
1782 editorComp = null;
1783 cellEditor = null;
1784 requestFocusInWindow(false);
1785 repaint();
1788 public void editingStopped (ChangeEvent event)
1790 if (rowBeingEdited > -1 && columnBeingEdited > -1)
1792 if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField)
1794 remove((Component)getValueAt(rowBeingEdited, columnBeingEdited));
1795 setValueAt(((JTextField)editorComp).getText(),
1796 rowBeingEdited, columnBeingEdited);
1798 rowBeingEdited = -1;
1799 columnBeingEdited = -1;
1801 editorTimer.stop();
1802 editorComp = null;
1803 cellEditor = null;
1804 requestFocusInWindow(false);
1805 repaint();
1808 public void tableChanged (TableModelEvent event)
1810 // update the column model from the table model if the structure has
1811 // changed and the flag autoCreateColumnsFromModel is set
1812 if ((event.getFirstRow() ==TableModelEvent.HEADER_ROW)
1813 && autoCreateColumnsFromModel)
1815 createDefaultColumnsFromModel();
1817 // If the structure changes, we need to revalidate, since that might
1818 // affect the size parameters of the JTable. Otherwise we only need
1819 // to perform a repaint to update the view.
1820 if (event.getType() == TableModelEvent.INSERT)
1821 revalidate();
1822 else if (event.getType() == TableModelEvent.DELETE)
1824 if (dataModel.getRowCount() == 0)
1825 clearSelection();
1826 revalidate();
1828 repaint();
1831 public void valueChanged (ListSelectionEvent event)
1833 repaint();
1837 * Returns index of the column that contains specified point
1838 * or -1 if this table doesn't contain this point.
1840 * @param point point to identify the column
1841 * @return index of the column that contains specified point or
1842 * -1 if this table doesn't contain this point.
1844 public int columnAtPoint(Point point)
1846 if (point != null)
1848 int ncols = getColumnCount();
1849 Dimension gap = getIntercellSpacing();
1850 TableColumnModel cols = getColumnModel();
1851 int x = point.x;
1853 for (int i = 0; i < ncols; ++i)
1855 int width = cols.getColumn(i).getWidth()
1856 + (gap == null ? 0 : gap.width);
1857 if (0 <= x && x < width)
1858 return i;
1859 x -= width;
1862 return -1;
1866 * Returns index of the row that contains specified point or
1867 * -1 if this table doesn't contain this point.
1869 * @param point point to identify the row
1870 * @return index of the row that contains specified point or
1871 * -1 if this table doesn't contain this point.
1873 public int rowAtPoint(Point point)
1875 if (point != null)
1877 int nrows = getRowCount();
1878 int height = getRowHeight();
1879 int y = point.y;
1881 for (int i = 0; i < nrows; ++i)
1883 if (0 <= y && y < height)
1884 return i;
1885 y -= height;
1888 return -1;
1891 /**
1892 * Calculate the visible rectangle for a particular row and column. The
1893 * row and column are specified in visual terms; the column may not match
1894 * the {@link #dataModel} column.
1896 * @param row the visible row to get the cell rectangle of
1898 * @param column the visible column to get the cell rectangle of, which may
1899 * differ from the {@link #dataModel} column
1901 * @param includeSpacing whether or not to include the cell margins in the
1902 * resulting cell. If <code>false</code>, the result will only contain the
1903 * inner area of the target cell, not including its margins.
1905 * @return a rectangle enclosing the specified cell
1907 public Rectangle getCellRect(int row,
1908 int column,
1909 boolean includeSpacing)
1911 int height = getRowHeight(row);
1912 int width = columnModel.getColumn(column).getWidth();
1913 int x_gap = columnModel.getColumnMargin();
1914 int y_gap = rowMargin;
1916 column = Math.max(0, Math.min(column, getColumnCount() - 1));
1917 row = Math.max(0, Math.min(row, getRowCount() - 1));
1919 int x = 0;
1920 int y = (height + y_gap) * row;
1922 for (int i = 0; i < column; ++i)
1923 x += columnModel.getColumn(i).getWidth();
1925 if (includeSpacing)
1926 return new Rectangle(x, y, width, height);
1927 else
1928 return new Rectangle(x, y, width - x_gap, height - y_gap);
1931 public void clearSelection()
1933 selectionModel.clearSelection();
1934 getColumnModel().getSelectionModel().clearSelection();
1938 * Get the value of the selectedRow property by delegation to
1939 * the {@link ListSelectionModel#getMinSelectionIndex} method of the
1940 * {@link #selectionModel} field.
1942 * @return The current value of the selectedRow property
1944 public int getSelectedRow ()
1946 return selectionModel.getMinSelectionIndex();
1950 * Get the value of the {@link #selectionModel} property.
1952 * @return The current value of the property
1954 public ListSelectionModel getSelectionModel()
1956 //Neither Sun nor IBM returns null if rowSelection not allowed
1957 return selectionModel;
1960 public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
1962 if (orientation == SwingConstants.VERTICAL)
1963 return visibleRect.height * direction;
1964 else
1965 return visibleRect.width * direction;
1969 * Get the value of the <code>scrollableTracksViewportHeight</code> property.
1971 * @return The constant value <code>false</code>
1973 public boolean getScrollableTracksViewportHeight()
1975 return false;
1979 * Get the value of the <code>scrollableTracksViewportWidth</code> property.
1981 * @return <code>true</code> unless the {@link #autoResizeMode} property is
1982 * <code>AUTO_RESIZE_OFF</code>
1984 public boolean getScrollableTracksViewportWidth()
1986 if (autoResizeMode == AUTO_RESIZE_OFF)
1987 return false;
1988 else
1989 return true;
1992 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
1994 // FIXME: I don't exactly know what sun does here. in both cases they
1995 // pick values which do *not* simply expose the next cell in a given
1996 // scroll direction.
1998 if (orientation == SwingConstants.VERTICAL)
1999 return direction * rowHeight;
2000 else
2002 int sum = 0;
2003 for (int i = 0; i < getColumnCount(); ++i)
2004 sum += columnModel.getColumn(0).getWidth();
2005 int inc = getColumnCount() == 0 ? 10 : sum / getColumnCount();
2006 return direction * inc;
2011 public TableCellEditor getCellEditor(int row, int column)
2013 TableCellEditor editor = columnModel.getColumn(column).getCellEditor();
2015 if (editor == null)
2016 editor = getDefaultEditor(dataModel.getColumnClass(column));
2018 return editor;
2021 public TableCellEditor getDefaultEditor(Class columnClass)
2023 if (defaultEditorsByColumnClass.containsKey(columnClass))
2024 return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass);
2025 else
2027 // FIXME: We have at least an editor for Object.class in our defaults.
2028 TableCellEditor r = new DefaultCellEditor(new JTextField());
2029 defaultEditorsByColumnClass.put(columnClass, r);
2030 return r;
2034 public TableCellRenderer getCellRenderer(int row, int column)
2036 TableCellRenderer renderer =
2037 columnModel.getColumn(column).getCellRenderer();
2038 if (renderer == null)
2039 renderer = getDefaultRenderer(getColumnClass(column));
2041 return renderer;
2044 public void setDefaultRenderer(Class columnClass, TableCellRenderer rend)
2046 defaultRenderersByColumnClass.put(columnClass, rend);
2049 public TableCellRenderer getDefaultRenderer(Class columnClass)
2051 if (defaultRenderersByColumnClass.containsKey(columnClass))
2052 return (TableCellRenderer) defaultRenderersByColumnClass.get(columnClass);
2053 else
2055 TableCellRenderer r = new DefaultTableCellRenderer();
2056 defaultRenderersByColumnClass.put(columnClass, r);
2057 return r;
2061 public int convertColumnIndexToModel(int vc)
2063 if (vc < 0)
2064 return vc;
2065 else
2066 return columnModel.getColumn(vc).getModelIndex();
2069 public int convertColumnIndexToView(int mc)
2071 if (mc < 0)
2072 return mc;
2073 int ncols = getColumnCount();
2074 for (int vc = 0; vc < ncols; ++vc)
2076 if (columnModel.getColumn(vc).getModelIndex() == mc)
2077 return vc;
2079 return -1;
2082 public Component prepareRenderer(TableCellRenderer renderer,
2083 int row,
2084 int column)
2087 boolean rowSelAllowed = getRowSelectionAllowed();
2088 boolean colSelAllowed = getColumnSelectionAllowed();
2089 boolean isSel = false;
2090 if (rowSelAllowed && colSelAllowed || !rowSelAllowed && !colSelAllowed)
2091 isSel = isCellSelected(row, column);
2092 else
2093 isSel = isRowSelected(row) && getRowSelectionAllowed()
2094 || isColumnSelected(column) && getColumnSelectionAllowed();
2096 // Determine the focused cell. The focused cell is the cell at the
2097 // leadSelectionIndices of the row and column selection model.
2098 ListSelectionModel rowSel = getSelectionModel();
2099 ListSelectionModel colSel = getColumnModel().getSelectionModel();
2100 boolean hasFocus = hasFocus() && isEnabled()
2101 && rowSel.getLeadSelectionIndex() == row
2102 && colSel.getLeadSelectionIndex() == column;
2104 return renderer.getTableCellRendererComponent(this,
2105 dataModel.getValueAt(row,
2106 convertColumnIndexToModel(column)),
2107 isSel,
2108 hasFocus,
2109 row, column);
2114 * Get the value of the {@link #autoCreateColumnsFromModel} property.
2116 * @return The current value of the property
2118 public boolean getAutoCreateColumnsFromModel()
2120 return autoCreateColumnsFromModel;
2124 * Get the value of the {@link #autoResizeMode} property.
2126 * @return The current value of the property
2128 public int getAutoResizeMode()
2130 return autoResizeMode;
2134 * Get the value of the {@link #rowHeight} property.
2136 * @return The current value of the property
2138 public int getRowHeight()
2140 return rowHeight;
2144 * Get the height of the specified row.
2146 * @param row the row whose height to return
2148 public int getRowHeight(int row)
2150 // FIXME: return the height of the specified row
2151 // which may be different from the general rowHeight
2152 return rowHeight;
2157 * Get the value of the {@link #rowMargin} property.
2159 * @return The current value of the property
2161 public int getRowMargin()
2163 return rowMargin;
2167 * Get the value of the {@link #rowSelectionAllowed} property.
2169 * @return The current value of the property
2171 public boolean getRowSelectionAllowed()
2173 return rowSelectionAllowed;
2177 * Get the value of the {@link #cellSelectionEnabled} property.
2179 * @return The current value of the property
2181 public boolean getCellSelectionEnabled()
2183 return getColumnSelectionAllowed() && getRowSelectionAllowed();
2187 * Get the value of the {@link #dataModel} property.
2189 * @return The current value of the property
2191 public TableModel getModel()
2193 return dataModel;
2197 * Get the value of the <code>columnCount</code> property by
2198 * delegation to the @{link #columnModel} field.
2200 * @return The current value of the columnCount property
2202 public int getColumnCount()
2204 return columnModel.getColumnCount();
2208 * Get the value of the <code>rowCount</code> property by
2209 * delegation to the @{link #dataModel} field.
2211 * @return The current value of the rowCount property
2213 public int getRowCount()
2215 return dataModel.getRowCount();
2219 * Get the value of the {@link #columnModel} property.
2221 * @return The current value of the property
2223 public TableColumnModel getColumnModel()
2225 return columnModel;
2229 * Get the value of the <code>selectedColumn</code> property by
2230 * delegation to the @{link #columnModel} field.
2232 * @return The current value of the selectedColumn property
2234 public int getSelectedColumn()
2236 return columnModel.getSelectionModel().getMinSelectionIndex();
2239 private static int countSelections(ListSelectionModel lsm)
2241 int lo = lsm.getMinSelectionIndex();
2242 int hi = lsm.getMaxSelectionIndex();
2243 int sum = 0;
2244 if (lo != -1 && hi != -1)
2246 switch (lsm.getSelectionMode())
2248 case ListSelectionModel.SINGLE_SELECTION:
2249 sum = 1;
2250 break;
2252 case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
2253 sum = hi - lo + 1;
2254 break;
2256 case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
2257 for (int i = lo; i <= hi; ++i)
2258 if (lsm.isSelectedIndex(i))
2259 ++sum;
2260 break;
2263 return sum;
2266 private static int[] getSelections(ListSelectionModel lsm)
2268 int sz = countSelections(lsm);
2269 int [] ret = new int[sz];
2271 int lo = lsm.getMinSelectionIndex();
2272 int hi = lsm.getMaxSelectionIndex();
2273 int j = 0;
2274 if (lo != -1 && hi != -1)
2276 switch (lsm.getSelectionMode())
2278 case ListSelectionModel.SINGLE_SELECTION:
2279 ret[0] = lo;
2280 break;
2282 case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
2283 for (int i = lo; i <= hi; ++i)
2284 ret[j++] = i;
2285 break;
2287 case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
2288 for (int i = lo; i <= hi; ++i)
2289 if (lsm.isSelectedIndex(i))
2290 ret[j++] = i;
2291 break;
2294 return ret;
2298 * Get the value of the <code>selectedColumnCount</code> property by
2299 * delegation to the @{link #columnModel} field.
2301 * @return The current value of the selectedColumnCount property
2303 public int getSelectedColumnCount()
2305 return countSelections(columnModel.getSelectionModel());
2309 * Get the value of the <code>selectedColumns</code> property by
2310 * delegation to the @{link #columnModel} field.
2312 * @return The current value of the selectedColumns property
2314 public int[] getSelectedColumns()
2316 return getSelections(columnModel.getSelectionModel());
2320 * Get the value of the <code>columnSelectionAllowed</code> property.
2322 * @return The current value of the columnSelectionAllowed property
2324 public boolean getColumnSelectionAllowed()
2326 return getColumnModel().getColumnSelectionAllowed();
2330 * Get the value of the <code>selectedRowCount</code> property by
2331 * delegation to the @{link #selectionModel} field.
2333 * @return The current value of the selectedRowCount property
2335 public int getSelectedRowCount()
2337 return countSelections(selectionModel);
2341 * Get the value of the <code>selectedRows</code> property by
2342 * delegation to the @{link #selectionModel} field.
2344 * @return The current value of the selectedRows property
2346 public int[] getSelectedRows()
2348 return getSelections(selectionModel);
2352 * Get the value of the {@link #accessibleContext} property.
2354 * @return The current value of the property
2356 public AccessibleContext getAccessibleContext()
2358 return accessibleContext;
2362 * Get the value of the {@link #cellEditor} property.
2364 * @return The current value of the property
2366 public TableCellEditor getCellEditor()
2368 return cellEditor;
2372 * Get the value of the {@link #dragEnabled} property.
2374 * @return The current value of the property
2376 public boolean getDragEnabled()
2378 return dragEnabled;
2382 * Get the value of the {@link #gridColor} property.
2384 * @return The current value of the property
2386 public Color getGridColor()
2388 return gridColor;
2392 * Get the value of the <code>intercellSpacing</code> property.
2394 * @return The current value of the property
2396 public Dimension getIntercellSpacing()
2398 return new Dimension(columnModel.getColumnMargin(), rowMargin);
2402 * Get the value of the {@link #preferredViewportSize} property.
2404 * @return The current value of the property
2406 public Dimension getPreferredScrollableViewportSize()
2408 return preferredViewportSize;
2412 * Get the value of the {@link #selectionBackground} property.
2414 * @return The current value of the property
2416 public Color getSelectionBackground()
2418 return selectionBackground;
2422 * Get the value of the {@link #selectionForeground} property.
2424 * @return The current value of the property
2426 public Color getSelectionForeground()
2428 return selectionForeground;
2432 * Get the value of the {@link #showHorizontalLines} property.
2434 * @return The current value of the property
2436 public boolean getShowHorizontalLines()
2438 return showHorizontalLines;
2442 * Get the value of the {@link #showVerticalLines} property.
2444 * @return The current value of the property
2446 public boolean getShowVerticalLines()
2448 return showVerticalLines;
2452 * Get the value of the {@link #tableHeader} property.
2454 * @return The current value of the property
2456 public JTableHeader getTableHeader()
2458 return tableHeader;
2462 * Removes specified column from displayable columns of this table.
2464 * @param column column to removed
2466 public void removeColumn(TableColumn column)
2468 columnModel.removeColumn(column);
2472 * Moves column at the specified index to new given location.
2474 * @param column index of the column to move
2475 * @param targetColumn index specifying new location of the column
2477 public void moveColumn(int column,int targetColumn)
2479 columnModel.moveColumn(column, targetColumn);
2483 * Set the value of the {@link #autoCreateColumnsFromModel} flag. If the
2484 * flag changes from <code>false</code> to <code>true</code>, the
2485 * {@link #createDefaultColumnsFromModel()} method is called.
2487 * @param autoCreate the new value of the flag.
2489 public void setAutoCreateColumnsFromModel(boolean autoCreate)
2491 if (autoCreateColumnsFromModel != autoCreate)
2493 autoCreateColumnsFromModel = autoCreate;
2494 if (autoCreate)
2495 createDefaultColumnsFromModel();
2500 * Set the value of the {@link #autoResizeMode} property.
2502 * @param a The new value of the autoResizeMode property
2504 public void setAutoResizeMode(int a)
2506 autoResizeMode = a;
2507 revalidate();
2508 repaint();
2512 * Set the value of the {@link #rowHeight} property.
2514 * @param r The new value of the rowHeight property
2516 public void setRowHeight(int r)
2518 if (r < 1)
2519 throw new IllegalArgumentException();
2521 rowHeight = r;
2522 revalidate();
2523 repaint();
2527 * Sets the value of the rowHeight property for the specified
2528 * row.
2530 * @param rh is the new rowHeight
2531 * @param row is the row to change the rowHeight of
2533 public void setRowHeight(int row, int rh)
2535 setRowHeight(rh);
2536 // FIXME: not implemented
2540 * Set the value of the {@link #rowMargin} property.
2542 * @param r The new value of the rowMargin property
2544 public void setRowMargin(int r)
2546 rowMargin = r;
2547 revalidate();
2548 repaint();
2552 * Set the value of the {@link #rowSelectionAllowed} property.
2554 * @param r The new value of the rowSelectionAllowed property
2556 public void setRowSelectionAllowed(boolean r)
2558 rowSelectionAllowed = r;
2559 repaint();
2563 * Set the value of the {@link #cellSelectionEnabled} property.
2565 * @param c The new value of the cellSelectionEnabled property
2567 public void setCellSelectionEnabled(boolean c)
2569 setColumnSelectionAllowed(c);
2570 setRowSelectionAllowed(c);
2571 // for backward-compatibility sake:
2572 cellSelectionEnabled = true;
2576 * <p>Set the value of the {@link #dataModel} property.</p>
2578 * <p>Unregister <code>this</code> as a {@link TableModelListener} from
2579 * previous {@link #dataModel} and register it with new parameter
2580 * <code>m</code>.</p>
2582 * @param m The new value of the model property
2584 public void setModel(TableModel m)
2586 // Throw exception is m is null.
2587 if (m == null)
2588 throw new IllegalArgumentException();
2590 // Don't do anything if setting the current model again.
2591 if (dataModel == m)
2592 return;
2594 TableModel oldModel = dataModel;
2596 // Remove table as TableModelListener from old model.
2597 if (dataModel != null)
2598 dataModel.removeTableModelListener(this);
2600 if (m != null)
2602 // Set property.
2603 dataModel = m;
2605 // Add table as TableModelListener to new model.
2606 dataModel.addTableModelListener(this);
2608 // Automatically create columns.
2609 if (autoCreateColumnsFromModel)
2610 createDefaultColumnsFromModel();
2613 // This property is bound, so we fire a property change event.
2614 firePropertyChange("model", oldModel, dataModel);
2616 // Repaint table.
2617 revalidate();
2618 repaint();
2622 * <p>Set the value of the {@link #columnModel} property.</p>
2624 * <p>Unregister <code>this</code> as a {@link TableColumnModelListener}
2625 * from previous {@link #columnModel} and register it with new parameter
2626 * <code>c</code>.</p>
2628 * @param c The new value of the columnModel property
2630 public void setColumnModel(TableColumnModel c)
2632 if (c == null)
2633 throw new IllegalArgumentException();
2634 TableColumnModel tmp = columnModel;
2635 if (tmp != null)
2636 tmp.removeColumnModelListener(this);
2637 if (c != null)
2638 c.addColumnModelListener(this);
2639 columnModel = c;
2640 if (dataModel != null && columnModel != null)
2642 int ncols = getColumnCount();
2643 for (int i = 0; i < ncols; ++i)
2644 columnModel.getColumn(i).setHeaderValue(dataModel.getColumnName(i));
2647 // according to Sun's spec we also have to set the tableHeader's
2648 // column model here
2649 if (tableHeader != null)
2650 tableHeader.setColumnModel(c);
2652 revalidate();
2653 repaint();
2657 * Set the value of the <code>columnSelectionAllowed</code> property.
2659 * @param c The new value of the property
2661 public void setColumnSelectionAllowed(boolean c)
2663 getColumnModel().setColumnSelectionAllowed(c);
2664 repaint();
2668 * <p>Set the value of the {@link #selectionModel} property.</p>
2670 * <p>Unregister <code>this</code> as a {@link ListSelectionListener}
2671 * from previous {@link #selectionModel} and register it with new
2672 * parameter <code>s</code>.</p>
2674 * @param s The new value of the selectionModel property
2676 public void setSelectionModel(ListSelectionModel s)
2678 if (s == null)
2679 throw new IllegalArgumentException();
2680 ListSelectionModel tmp = selectionModel;
2681 if (tmp != null)
2682 tmp.removeListSelectionListener(this);
2683 if (s != null)
2684 s.addListSelectionListener(this);
2685 selectionModel = s;
2689 * Set the value of the <code>selectionMode</code> property by
2690 * delegation to the {@link #selectionModel} field. The same selection
2691 * mode is set for row and column selection models.
2693 * @param s The new value of the property
2695 public void setSelectionMode(int s)
2697 selectionModel.setSelectionMode(s);
2698 columnModel.getSelectionModel().setSelectionMode(s);
2700 repaint();
2704 * <p>Set the value of the {@link #cellEditor} property.</p>
2706 * <p>Unregister <code>this</code> as a {@link CellEditorListener} from
2707 * previous {@link #cellEditor} and register it with new parameter
2708 * <code>c</code>.</p>
2710 * @param c The new value of the cellEditor property
2712 public void setCellEditor(TableCellEditor c)
2714 TableCellEditor tmp = cellEditor;
2715 if (tmp != null)
2716 tmp.removeCellEditorListener(this);
2717 if (c != null)
2718 c.addCellEditorListener(this);
2719 cellEditor = c;
2723 * Set the value of the {@link #dragEnabled} property.
2725 * @param d The new value of the dragEnabled property
2727 public void setDragEnabled(boolean d)
2729 dragEnabled = d;
2733 * Set the value of the {@link #gridColor} property.
2735 * @param g The new value of the gridColor property
2737 public void setGridColor(Color g)
2739 gridColor = g;
2740 repaint();
2744 * Set the value of the <code>intercellSpacing</code> property.
2746 * @param i The new value of the intercellSpacing property
2748 public void setIntercellSpacing(Dimension i)
2750 rowMargin = i.height;
2751 columnModel.setColumnMargin(i.width);
2752 repaint();
2756 * Set the value of the {@link #preferredViewportSize} property.
2758 * @param p The new value of the preferredViewportSize property
2760 public void setPreferredScrollableViewportSize(Dimension p)
2762 preferredViewportSize = p;
2763 revalidate();
2764 repaint();
2768 * <p>Set the value of the {@link #selectionBackground} property.</p>
2770 * <p>Fire a PropertyChangeEvent with name {@link
2771 * #SELECTION_BACKGROUND_CHANGED_PROPERTY} to registered listeners, if
2772 * selectionBackground changed.</p>
2774 * @param s The new value of the selectionBackground property
2776 public void setSelectionBackground(Color s)
2778 Color tmp = selectionBackground;
2779 selectionBackground = s;
2780 if (((tmp == null && s != null)
2781 || (s == null && tmp != null)
2782 || (tmp != null && s != null && !tmp.equals(s))))
2783 firePropertyChange(SELECTION_BACKGROUND_CHANGED_PROPERTY, tmp, s);
2784 repaint();
2788 * <p>Set the value of the {@link #selectionForeground} property.</p>
2790 * <p>Fire a PropertyChangeEvent with name {@link
2791 * #SELECTION_FOREGROUND_CHANGED_PROPERTY} to registered listeners, if
2792 * selectionForeground changed.</p>
2794 * @param s The new value of the selectionForeground property
2796 public void setSelectionForeground(Color s)
2798 Color tmp = selectionForeground;
2799 selectionForeground = s;
2800 if (((tmp == null && s != null)
2801 || (s == null && tmp != null)
2802 || (tmp != null && s != null && !tmp.equals(s))))
2803 firePropertyChange(SELECTION_FOREGROUND_CHANGED_PROPERTY, tmp, s);
2804 repaint();
2808 * Set the value of the <code>showGrid</code> property.
2810 * @param s The new value of the showGrid property
2812 public void setShowGrid(boolean s)
2814 setShowVerticalLines(s);
2815 setShowHorizontalLines(s);
2819 * Set the value of the {@link #showHorizontalLines} property.
2821 * @param s The new value of the showHorizontalLines property
2823 public void setShowHorizontalLines(boolean s)
2825 showHorizontalLines = s;
2826 repaint();
2830 * Set the value of the {@link #showVerticalLines} property.
2832 * @param s The new value of the showVerticalLines property
2834 public void setShowVerticalLines(boolean s)
2836 showVerticalLines = s;
2837 repaint();
2841 * Set the value of the {@link #tableHeader} property.
2843 * @param t The new value of the tableHeader property
2845 public void setTableHeader(JTableHeader t)
2847 if (tableHeader != null)
2848 tableHeader.setTable(null);
2849 tableHeader = t;
2850 if (tableHeader != null)
2851 tableHeader.setTable(this);
2852 revalidate();
2853 repaint();
2856 protected void configureEnclosingScrollPane()
2858 JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
2859 if (jsp != null && tableHeader != null)
2861 jsp.setColumnHeaderView(tableHeader);
2865 protected void unconfigureEnclosingScrollPane()
2867 JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
2868 if (jsp != null)
2870 jsp.setColumnHeaderView(null);
2875 public void addNotify()
2877 super.addNotify();
2878 configureEnclosingScrollPane();
2881 public void removeNotify()
2883 super.addNotify();
2884 unconfigureEnclosingScrollPane();
2889 * This distributes the superfluous width in a table evenly on its columns.
2891 * The implementation used here is different to that one described in
2892 * the JavaDocs. It is much simpler, and seems to work very well.
2894 * TODO: correctly implement the algorithm described in the JavaDoc
2896 private void distributeSpill(TableColumn[] cols, int spill)
2898 int average = spill / cols.length;
2899 for (int i = 0; i < cols.length; i++)
2901 if (cols[i] != null)
2902 cols[i].setWidth(cols[i].getWidth() + average);
2906 public void doLayout()
2908 TableColumn resizingColumn = null;
2910 int ncols = getColumnCount();
2911 if (ncols < 1)
2912 return;
2914 int[] pref = new int[ncols];
2915 int prefSum = 0;
2916 int rCol = -1;
2918 if (tableHeader != null)
2919 resizingColumn = tableHeader.getResizingColumn();
2921 for (int i = 0; i < ncols; ++i)
2923 TableColumn col = columnModel.getColumn(i);
2924 int p = col.getWidth();
2925 pref[i] = p;
2926 prefSum += p;
2927 if (resizingColumn == col)
2928 rCol = i;
2931 int spill = getWidth() - prefSum;
2933 if (resizingColumn != null)
2935 TableColumn col;
2936 TableColumn [] cols;
2938 switch (getAutoResizeMode())
2940 case AUTO_RESIZE_LAST_COLUMN:
2941 col = columnModel.getColumn(ncols-1);
2942 col.setWidth(col.getPreferredWidth() + spill);
2943 break;
2945 case AUTO_RESIZE_NEXT_COLUMN:
2946 col = columnModel.getColumn(ncols-1);
2947 col.setWidth(col.getPreferredWidth() + spill);
2948 break;
2950 case AUTO_RESIZE_ALL_COLUMNS:
2951 cols = new TableColumn[ncols];
2952 for (int i = 0; i < ncols; ++i)
2953 cols[i] = columnModel.getColumn(i);
2954 distributeSpill(cols, spill);
2955 break;
2957 case AUTO_RESIZE_SUBSEQUENT_COLUMNS:
2958 cols = new TableColumn[ncols];
2959 for (int i = rCol; i < ncols; ++i)
2960 cols[i] = columnModel.getColumn(i);
2961 distributeSpill(cols, spill);
2962 break;
2964 case AUTO_RESIZE_OFF:
2965 default:
2966 int prefWidth = resizingColumn.getPreferredWidth();
2967 resizingColumn.setWidth(prefWidth);
2970 else
2972 TableColumn [] cols = new TableColumn[ncols];
2973 for (int i = 0; i < ncols; ++i)
2974 cols[i] = columnModel.getColumn(i);
2975 distributeSpill(cols, spill);
2980 * @deprecated Replaced by <code>doLayout()</code>
2982 public void sizeColumnsToFit(boolean lastColumnOnly)
2984 doLayout();
2988 * Obsolete since JDK 1.4. Please use <code>doLayout()</code>.
2990 public void sizeColumnsToFit(int resizingColumn)
2992 doLayout();
2995 public String getUIClassID()
2997 return "TableUI";
3001 * This method returns the table's UI delegate.
3003 * @return The table's UI delegate.
3005 public TableUI getUI()
3007 return (TableUI) ui;
3011 * This method sets the table's UI delegate.
3013 * @param ui The table's UI delegate.
3015 public void setUI(TableUI ui)
3017 super.setUI(ui);
3020 public void updateUI()
3022 setUI((TableUI) UIManager.getUI(this));
3023 revalidate();
3024 repaint();
3027 public Class getColumnClass(int column)
3029 return getModel().getColumnClass(column);
3032 public String getColumnName(int column)
3034 int modelColumn = columnModel.getColumn(column).getModelIndex();
3035 return dataModel.getColumnName(modelColumn);
3038 public int getEditingColumn()
3040 return editingColumn;
3043 public void setEditingColumn(int column)
3045 editingColumn = column;
3048 public int getEditingRow()
3050 return editingRow;
3053 public void setEditingRow(int column)
3055 editingRow = column;
3058 public Component getEditorComponent()
3060 return editorComp;
3063 public boolean isEditing()
3065 return editorComp != null;
3068 public void setDefaultEditor(Class columnClass, TableCellEditor editor)
3070 if (editor != null)
3071 defaultEditorsByColumnClass.put(columnClass, editor);
3072 else
3073 defaultEditorsByColumnClass.remove(columnClass);
3076 public void addColumnSelectionInterval(int index0, int index1)
3078 if ((index0 < 0 || index0 > (getColumnCount()-1)
3079 || index1 < 0 || index1 > (getColumnCount()-1)))
3080 throw new IllegalArgumentException("Column index out of range.");
3082 getColumnModel().getSelectionModel().addSelectionInterval(index0, index1);
3085 public void addRowSelectionInterval(int index0, int index1)
3087 if ((index0 < 0 || index0 > (getRowCount()-1)
3088 || index1 < 0 || index1 > (getRowCount()-1)))
3089 throw new IllegalArgumentException("Row index out of range.");
3091 getSelectionModel().addSelectionInterval(index0, index1);
3094 public void setColumnSelectionInterval(int index0, int index1)
3096 if ((index0 < 0 || index0 > (getColumnCount()-1)
3097 || index1 < 0 || index1 > (getColumnCount()-1)))
3098 throw new IllegalArgumentException("Column index out of range.");
3100 getColumnModel().getSelectionModel().setSelectionInterval(index0, index1);
3103 public void setRowSelectionInterval(int index0, int index1)
3105 if ((index0 < 0 || index0 > (getRowCount()-1)
3106 || index1 < 0 || index1 > (getRowCount()-1)))
3107 throw new IllegalArgumentException("Row index out of range.");
3109 getSelectionModel().setSelectionInterval(index0, index1);
3112 public void removeColumnSelectionInterval(int index0, int index1)
3114 if ((index0 < 0 || index0 > (getColumnCount()-1)
3115 || index1 < 0 || index1 > (getColumnCount()-1)))
3116 throw new IllegalArgumentException("Column index out of range.");
3118 getColumnModel().getSelectionModel().removeSelectionInterval(index0, index1);
3121 public void removeRowSelectionInterval(int index0, int index1)
3123 if ((index0 < 0 || index0 > (getRowCount()-1)
3124 || index1 < 0 || index1 > (getRowCount()-1)))
3125 throw new IllegalArgumentException("Row index out of range.");
3127 getSelectionModel().removeSelectionInterval(index0, index1);
3130 public boolean isColumnSelected(int column)
3132 return getColumnModel().getSelectionModel().isSelectedIndex(column);
3135 public boolean isRowSelected(int row)
3137 return getSelectionModel().isSelectedIndex(row);
3140 public boolean isCellSelected(int row, int column)
3142 return isRowSelected(row) && isColumnSelected(column);
3145 public void selectAll()
3147 // rowLead and colLead store the current lead selection indices
3148 int rowLead = selectionModel.getLeadSelectionIndex();
3149 int colLead = getColumnModel().getSelectionModel().getLeadSelectionIndex();
3150 // the following calls to setSelectionInterval change the lead selection
3151 // indices
3152 setColumnSelectionInterval(0, getColumnCount() - 1);
3153 setRowSelectionInterval(0, getRowCount() - 1);
3154 // the following addSelectionInterval calls restore the lead selection
3155 // indices to their previous values
3156 addColumnSelectionInterval(colLead,colLead);
3157 addRowSelectionInterval(rowLead, rowLead);
3160 public Object getValueAt(int row, int column)
3162 return dataModel.getValueAt(row, convertColumnIndexToModel(column));
3165 public void setValueAt(Object value, int row, int column)
3167 if (!isCellEditable(row, column))
3168 return;
3170 if (value instanceof Component)
3171 add((Component)value);
3172 dataModel.setValueAt(value, row, convertColumnIndexToModel(column));
3175 public TableColumn getColumn(Object identifier)
3177 return columnModel.getColumn(columnModel.getColumnIndex(identifier));
3181 * Returns <code>true</code> if the specified cell is editable, and
3182 * <code>false</code> otherwise.
3184 * @param row the row index.
3185 * @param column the column index.
3187 * @return A boolean.
3189 public boolean isCellEditable(int row, int column)
3191 return dataModel.isCellEditable(row, convertColumnIndexToModel(column));
3195 * Clears any existing columns from the <code>JTable</code>'s
3196 * {@link TableColumnModel} and creates new columns to match the values in
3197 * the data ({@link TableModel}) used by the table.
3199 * @see #setAutoCreateColumnsFromModel(boolean)
3201 public void createDefaultColumnsFromModel()
3203 assert columnModel != null : "The columnModel must not be null.";
3205 // remove existing columns
3206 int columnIndex = columnModel.getColumnCount() - 1;
3207 while (columnIndex >= 0)
3209 columnModel.removeColumn(columnModel.getColumn(columnIndex));
3210 columnIndex--;
3213 // add new columns to match the TableModel
3214 int columnCount = dataModel.getColumnCount();
3215 for (int c = 0; c < columnCount; c++)
3217 TableColumn column = new TableColumn(c);
3218 column.setIdentifier(dataModel.getColumnName(c));
3219 column.setHeaderValue(dataModel.getColumnName(c));
3220 columnModel.addColumn(column);
3221 column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
3225 public void changeSelection (int rowIndex, int columnIndex, boolean toggle, boolean extend)
3227 if (toggle && extend)
3229 // Leave the selection state as is, but move the anchor
3230 // index to the specified location
3231 selectionModel.setAnchorSelectionIndex(rowIndex);
3232 getColumnModel().getSelectionModel().setAnchorSelectionIndex(columnIndex);
3234 else if (toggle)
3236 // Toggle the state of the specified cell
3237 if (isCellSelected(rowIndex,columnIndex))
3239 selectionModel.removeSelectionInterval(rowIndex,rowIndex);
3240 getColumnModel().getSelectionModel().removeSelectionInterval(columnIndex,columnIndex);
3242 else
3244 selectionModel.addSelectionInterval(rowIndex,rowIndex);
3245 getColumnModel().getSelectionModel().addSelectionInterval(columnIndex,columnIndex);
3248 else if (extend)
3250 // Extend the previous selection from the anchor to the
3251 // specified cell, clearing all other selections
3252 selectionModel.setLeadSelectionIndex(rowIndex);
3253 getColumnModel().getSelectionModel().setLeadSelectionIndex(columnIndex);
3255 else
3257 // Clear the previous selection and ensure the new cell
3258 // is selected
3259 selectionModel.clearSelection();
3260 selectionModel.setSelectionInterval(rowIndex,rowIndex);
3261 getColumnModel().getSelectionModel().clearSelection();
3262 getColumnModel().getSelectionModel().setSelectionInterval(columnIndex, columnIndex);
3269 * Programmatically starts editing the specified cell.
3271 * @param row the row of the cell to edit.
3272 * @param column the column of the cell to edit.
3274 public boolean editCellAt (int row, int column)
3276 oldCellValue = getValueAt(row, column);
3277 setCellEditor(getCellEditor(row, column));
3278 editorComp = prepareEditor(cellEditor, row, column);
3279 cellEditor.addCellEditorListener(this);
3280 rowBeingEdited = row;
3281 columnBeingEdited = column;
3282 setValueAt(editorComp, row, column);
3283 ((JTextField)editorComp).requestFocusInWindow(false);
3284 editorTimer.start();
3285 return true;
3289 * Programmatically starts editing the specified cell.
3291 * @param row the row of the cell to edit.
3292 * @param column the column of the cell to edit.
3294 public boolean editCellAt (int row, int column, EventObject e)
3296 return editCellAt(row, column);
3300 * Discards the editor object.
3302 public void removeEditor()
3304 editingStopped(new ChangeEvent(this));
3308 * Prepares the editor by querying for the value and selection state of the
3309 * cell at (row, column).
3311 * @param editor the TableCellEditor to set up
3312 * @param row the row of the cell to edit
3313 * @param column the column of the cell to edit
3314 * @return the Component being edited
3316 public Component prepareEditor (TableCellEditor editor, int row, int column)
3318 return editor.getTableCellEditorComponent
3319 (this, getValueAt(row, column), isCellSelected(row, column), row, column);
3323 * This revalidates the <code>JTable</code> and queues a repaint.
3325 protected void resizeAndRepaint()
3327 revalidate();
3328 repaint();
3332 * Sets whether cell editors of this table should receive keyboard focus
3333 * when the editor is activated by a keystroke. The default setting is
3334 * <code>false</code> which means that the table should keep the keyboard
3335 * focus until the cell is selected by a mouse click.
3337 * @param value the value to set
3339 * @since 1.4
3341 public void setSurrendersFocusOnKeystroke(boolean value)
3343 // TODO: Implement functionality of this property (in UI impl).
3344 surrendersFocusOnKeystroke = value;
3348 * Returns whether cell editors of this table should receive keyboard focus
3349 * when the editor is activated by a keystroke. The default setting is
3350 * <code>false</code> which means that the table should keep the keyboard
3351 * focus until the cell is selected by a mouse click.
3353 * @return whether cell editors of this table should receive keyboard focus
3354 * when the editor is activated by a keystroke
3356 * @since 1.4
3358 public boolean getSurrendersFocusOnKeystroke()
3360 // TODO: Implement functionality of this property (in UI impl).
3361 return surrendersFocusOnKeystroke;