2 Copyright (C) 2002, 2004, 2005, 2006 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)
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
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
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. */
41 import java
.awt
.Color
;
42 import java
.awt
.Component
;
43 import java
.awt
.Cursor
;
44 import java
.awt
.Dimension
;
46 import java
.awt
.FontMetrics
;
47 import java
.awt
.Point
;
48 import java
.awt
.Rectangle
;
49 import java
.awt
.event
.FocusListener
;
50 import java
.beans
.PropertyChangeEvent
;
51 import java
.beans
.PropertyChangeListener
;
52 import java
.text
.DateFormat
;
53 import java
.text
.NumberFormat
;
54 import java
.util
.Date
;
55 import java
.util
.EventObject
;
56 import java
.util
.Hashtable
;
57 import java
.util
.Locale
;
58 import java
.util
.Vector
;
60 import javax
.accessibility
.Accessible
;
61 import javax
.accessibility
.AccessibleComponent
;
62 import javax
.accessibility
.AccessibleContext
;
63 import javax
.accessibility
.AccessibleExtendedTable
;
64 import javax
.accessibility
.AccessibleRole
;
65 import javax
.accessibility
.AccessibleSelection
;
66 import javax
.accessibility
.AccessibleStateSet
;
67 import javax
.accessibility
.AccessibleTable
;
68 import javax
.accessibility
.AccessibleTableModelChange
;
69 import javax
.swing
.event
.CellEditorListener
;
70 import javax
.swing
.event
.ChangeEvent
;
71 import javax
.swing
.event
.ListSelectionEvent
;
72 import javax
.swing
.event
.ListSelectionListener
;
73 import javax
.swing
.event
.TableColumnModelEvent
;
74 import javax
.swing
.event
.TableColumnModelListener
;
75 import javax
.swing
.event
.TableModelEvent
;
76 import javax
.swing
.event
.TableModelListener
;
77 import javax
.swing
.plaf
.TableUI
;
78 import javax
.swing
.table
.DefaultTableCellRenderer
;
79 import javax
.swing
.table
.DefaultTableColumnModel
;
80 import javax
.swing
.table
.DefaultTableModel
;
81 import javax
.swing
.table
.JTableHeader
;
82 import javax
.swing
.table
.TableCellEditor
;
83 import javax
.swing
.table
.TableCellRenderer
;
84 import javax
.swing
.table
.TableColumn
;
85 import javax
.swing
.table
.TableColumnModel
;
86 import javax
.swing
.table
.TableModel
;
89 * The table component, displaying information, organized in rows and columns.
90 * The table can be placed in the scroll bar and have the optional header
91 * that is always visible. Cell values may be editable after double clicking
92 * on the cell. Cell columns may have various data types, that are
93 * displayed and edited by the different renderers and editors. It is possible
94 * to set different column width. The columns are also resizeable by
95 * dragging the column boundary in the header.
99 implements TableModelListener
, Scrollable
, TableColumnModelListener
,
100 ListSelectionListener
, CellEditorListener
, Accessible
103 * Provides accessibility support for <code>JTable</code>.
105 * @author Roman Kennke (kennke@aicas.com)
107 protected class AccessibleJTable
108 extends AccessibleJComponent
109 implements AccessibleSelection
, ListSelectionListener
, TableModelListener
,
110 TableColumnModelListener
, CellEditorListener
, PropertyChangeListener
,
111 AccessibleExtendedTable
115 * Provides accessibility support for table cells.
117 * @author Roman Kennke (kennke@aicas.com)
119 protected class AccessibleJTableCell
120 extends AccessibleContext
121 implements Accessible
, AccessibleComponent
125 * The table of this cell.
127 private JTable table
;
130 * The row index of this cell.
135 * The column index of this cell.
140 * The index of this cell inside the AccessibleJTable parent.
145 * Creates a new <code>AccessibleJTableCell</code>.
149 * @param c the column
150 * @param i the index of this cell inside the accessible table parent
152 public AccessibleJTableCell(JTable t
, int r
, int c
, int i
)
161 * Returns the accessible row for the table cell.
163 * @return the accessible row for the table cell
165 public AccessibleRole
getAccessibleRole()
167 // TODO: What is the role of the table cell?
168 return AccessibleRole
.UNKNOWN
;
172 * Returns the accessible state set of this accessible table cell.
174 * @return the accessible state set of this accessible table cell
176 public AccessibleStateSet
getAccessibleStateSet()
178 // TODO: What state shoiuld be returned here?
179 return new AccessibleStateSet();
183 * Returns the index of this cell in the parent object.
185 * @return the index of this cell in the parent object
187 public int getAccessibleIndexInParent()
193 * Returns the number of children of this object. Table cells cannot have
194 * children, so we return <code>0</code> here.
196 * @return <code>0</code>
198 public int getAccessibleChildrenCount()
204 * Returns the accessible child at index <code>i</code>. Table cells
205 * don't have children, so we return <code>null</code> here.
207 * @return <code>null</code>
209 public Accessible
getAccessibleChild(int i
)
215 * Returns the locale setting for this accessible table cell.
217 * @return the locale setting for this accessible table cell
219 public Locale
getLocale()
221 // TODO: For now, we return english here. This must be fixed as soon
222 // as we have a localized Swing.
223 return Locale
.ENGLISH
;
227 * Returns the accessible context of this table cell. Since accessible
228 * table cells are their own accessible context, we return
231 * @return the accessible context of this table cell
233 public AccessibleContext
getAccessibleContext()
239 * Returns the background color of this cell.
241 * @return the background color of this cell
243 public Color
getBackground()
245 return table
.getBackground();
249 * Sets the background of the cell. Since table cells cannot have
250 * individual background colors, this method does nothing. Set the
251 * background directly on the table instead.
253 * @param color not used
255 public void setBackground(Color color
)
257 // This method does nothing. See API comments.
261 * Returns the foreground color of the table cell.
263 * @return the foreground color of the table cell
265 public Color
getForeground()
267 return table
.getForeground();
271 * Sets the foreground of the cell. Since table cells cannot have
272 * individual foreground colors, this method does nothing. Set the
273 * foreground directly on the table instead.
275 * @param color not used
277 public void setForeground(Color color
)
279 // This method does nothing. See API comments.
283 * Returns the cursor for this table cell.
285 * @return the cursor for this table cell
287 public Cursor
getCursor()
289 return table
.getCursor();
293 * Sets the cursor of the cell. Since table cells cannot have
294 * individual cursors, this method does nothing. Set the
295 * cursor directly on the table instead.
297 * @param cursor not used
299 public void setCursor(Cursor cursor
)
301 // This method does nothing. See API comments.
305 * Returns the font of the table cell.
307 * @return the font of the table cell
309 public Font
getFont()
311 return table
.getFont();
315 * Sets the font of the cell. Since table cells cannot have
316 * individual fonts, this method does nothing. Set the
317 * font directly on the table instead.
319 * @param font not used
321 public void setFont(Font font
)
323 // This method does nothing. See API comments.
327 * Returns the font metrics for a specified font.
329 * @param font the font for which we return the metrics
331 * @return the font metrics for a specified font
333 public FontMetrics
getFontMetrics(Font font
)
335 return table
.getFontMetrics(font
);
339 * Returns <code>true</code> if this table cell is enabled,
340 * <code>false</code> otherwise.
342 * @return <code>true</code> if this table cell is enabled,
343 * <code>false</code> otherwise
345 public boolean isEnabled()
347 return table
.isEnabled();
351 * Table cells cannot be disabled or enabled individually, so this method
352 * does nothing. Set the enabled flag on the table itself.
354 * @param b not used here
356 public void setEnabled(boolean b
)
358 // This method does nothing. See API comments.
362 * Returns <code>true</code> if this cell is visible, <code>false</code>
365 * @return <code>true</code> if this cell is visible, <code>false</code>
368 public boolean isVisible()
370 return table
.isVisible();
374 * The visibility cannot be set on individual table cells, so this method
375 * does nothing. Set the visibility on the table itself.
379 public void setVisible(boolean b
)
381 // This method does nothing. See API comments.
385 * Returns <code>true</code> if this table cell is currently showing on
388 * @return <code>true</code> if this table cell is currently showing on
391 public boolean isShowing()
393 return table
.isShowing();
397 * Returns <code>true</code> if this table cell contains the location
398 * at <code>point</code>, <code>false</code> otherwise.
399 * <code>point</code> is interpreted as relative to the coordinate system
402 * @return <code>true</code> if this table cell contains the location
403 * at <code>point</code>, <code>false</code> otherwise
405 public boolean contains(Point point
)
407 Rectangle cellRect
= table
.getCellRect(row
, column
, true);
410 return cellRect
.contains(point
);
414 * Returns the screen location of the table cell.
416 * @return the screen location of the table cell
418 public Point
getLocationOnScreen()
420 Point tableLoc
= table
.getLocationOnScreen();
421 Rectangle cellRect
= table
.getCellRect(row
, column
, true);
422 tableLoc
.x
+= cellRect
.x
;
423 tableLoc
.y
+= cellRect
.y
;
428 * Returns the location of this cell relative to the table's bounds.
430 * @return the location of this cell relative to the table's bounds
432 public Point
getLocation()
434 Rectangle cellRect
= table
.getCellRect(row
, column
, true);
435 return new Point(cellRect
.x
, cellRect
.y
);
439 * The location of the table cells cannot be manipulated directly, so
440 * this method does nothing.
442 * @param point not used
444 public void setLocation(Point point
)
446 // This method does nothing. See API comments.
450 * Returns the bounds of the cell relative to its table.
452 * @return the bounds of the cell relative to its table
454 public Rectangle
getBounds()
456 return table
.getCellRect(row
, column
, true);
460 * The bounds of the table cells cannot be manipulated directly, so
461 * this method does nothing.
463 * @param rectangle not used
465 public void setBounds(Rectangle rectangle
)
467 // This method does nothing. See API comments.
471 * Returns the size of the table cell.
473 * @return the size of the table cell
475 public Dimension
getSize()
477 Rectangle cellRect
= table
.getCellRect(row
, column
, true);
478 return new Dimension(cellRect
.width
, cellRect
.height
);
482 * The size cannot be set on table cells directly, so this method does
485 * @param dimension not used
487 public void setSize(Dimension dimension
)
489 // This method does nothing. See API comments.
493 * Table cells have no children, so we return <code>null</code> here.
495 * @return <code>null</code>
497 public Accessible
getAccessibleAt(Point point
)
503 * Returns <code>true</code> if this table cell is focus traversable,
504 * <code>false</code> otherwise.
506 * @return <code>true</code> if this table cell is focus traversable,
507 * <code>false</code> otherwise
509 public boolean isFocusTraversable()
511 return table
.isFocusable();
515 * Requests that this table cell gets the keyboard focus.
517 public void requestFocus()
519 // We first set the selection models' lead selection to this cell.
520 table
.getColumnModel().getSelectionModel()
521 .setLeadSelectionIndex(column
);
522 table
.getSelectionModel().setLeadSelectionIndex(row
);
523 // Now we request that the table receives focus.
524 table
.requestFocus();
528 * Adds a focus listener to this cell. The focus listener is really
529 * added to the table, so there is no way to find out when an individual
530 * cell changes the focus.
532 * @param listener the focus listener to add
534 public void addFocusListener(FocusListener listener
)
536 table
.addFocusListener(listener
);
540 * Removes a focus listener from the cell. The focus listener is really
541 * removed from the table.
543 * @param listener the listener to remove
545 public void removeFocusListener(FocusListener listener
)
547 table
.removeFocusListener(listener
);
552 protected class AccessibleJTableModelChange
553 implements AccessibleTableModelChange
556 protected int firstRow
;
557 protected int lastRow
;
558 protected int firstColumn
;
559 protected int lastColumn
;
561 protected AccessibleJTableModelChange(int type
, int firstRow
,
562 int lastRow
, int firstColumn
,
566 this.firstRow
= firstRow
;
567 this.lastRow
= lastRow
;
568 this.firstColumn
= firstColumn
;
569 this.lastColumn
= lastColumn
;
577 public int getFirstRow()
582 public int getLastRow()
587 public int getFirstColumn()
592 public int getLastColumn()
599 * Creates a new <code>AccessibleJTable</code>.
603 protected AccessibleJTable()
605 getModel().addTableModelListener(this);
606 getSelectionModel().addListSelectionListener(this);
607 getColumnModel().addColumnModelListener(this);
608 getCellEditor().addCellEditorListener(this);
612 * Returns the number of selected items in this table.
614 public int getAccessibleSelectionCount()
616 return getSelectedColumnCount();
619 public Accessible
getAccessibleSelection(int i
)
621 // TODO Auto-generated method stub
625 public boolean isAccessibleChildSelected(int i
)
627 // TODO Auto-generated method stub
631 public void addAccessibleSelection(int i
)
633 // TODO Auto-generated method stub
637 public void removeAccessibleSelection(int i
)
639 // TODO Auto-generated method stub
643 public void clearAccessibleSelection()
645 // TODO Auto-generated method stub
649 public void selectAllAccessibleSelection()
651 // TODO Auto-generated method stub
655 public void valueChanged(ListSelectionEvent event
)
657 // TODO Auto-generated method stub
662 * Receives notification when the table model changes. Depending on the
663 * type of change, this method calls {@link #tableRowsInserted} or
664 * {@link #tableRowsDeleted}.
666 * @param event the table model event
668 public void tableChanged(TableModelEvent event
)
670 switch (event
.getType())
672 case TableModelEvent
.INSERT
:
673 tableRowsInserted(event
);
675 case TableModelEvent
.DELETE
:
676 tableRowsDeleted(event
);
682 * Receives notification when one or more rows have been inserted into the
685 * @param event the table model event
687 public void tableRowsInserted(TableModelEvent event
)
689 // TODO: What to do here, if anything? This might be a hook method for
694 * Receives notification when one or more rows have been deleted from the
697 * @param event the table model event
699 public void tableRowsDeleted(TableModelEvent event
)
701 // TODO: What to do here, if anything? This might be a hook method for
705 public void columnAdded(TableColumnModelEvent event
)
707 // TODO Auto-generated method stub
711 public void columnMarginChanged(ChangeEvent event
)
713 // TODO Auto-generated method stub
717 public void columnMoved(TableColumnModelEvent event
)
719 // TODO Auto-generated method stub
723 public void columnRemoved(TableColumnModelEvent event
)
725 // TODO Auto-generated method stub
729 public void columnSelectionChanged(ListSelectionEvent event
)
731 // TODO Auto-generated method stub
735 public void editingCanceled(ChangeEvent event
)
737 // TODO Auto-generated method stub
741 public void editingStopped(ChangeEvent event
)
743 // TODO Auto-generated method stub
748 * Receives notification when any of the JTable's properties changes. This
749 * is used to replace the listeners on the table's model, selection model,
750 * column model and cell editor.
752 * @param e the property change event
754 public void propertyChange(PropertyChangeEvent e
)
756 String propName
= e
.getPropertyName();
757 if (propName
.equals("tableModel"))
759 TableModel oldModel
= (TableModel
) e
.getOldValue();
760 oldModel
.removeTableModelListener(this);
761 TableModel newModel
= (TableModel
) e
.getNewValue();
762 newModel
.addTableModelListener(this);
764 else if (propName
.equals("columnModel"))
766 TableColumnModel oldModel
= (TableColumnModel
) e
.getOldValue();
767 oldModel
.removeColumnModelListener(this);
768 TableColumnModel newModel
= (TableColumnModel
) e
.getNewValue();
769 newModel
.addColumnModelListener(this);
771 else if (propName
.equals("selectionModel"))
773 ListSelectionModel oldModel
= (ListSelectionModel
) e
.getOldValue();
774 oldModel
.removeListSelectionListener(this);
775 ListSelectionModel newModel
= (ListSelectionModel
) e
.getNewValue();
776 newModel
.addListSelectionListener(this);
778 else if (propName
.equals("cellEditor"))
780 CellEditor oldEd
= (CellEditor
) e
.getOldValue();
781 oldEd
.removeCellEditorListener(this);
782 CellEditor newEd
= (CellEditor
) e
.getNewValue();
783 newEd
.addCellEditorListener(this);
787 public int getAccessibleRow(int index
)
789 // TODO Auto-generated method stub
793 public int getAccessibleColumn(int index
)
795 // TODO Auto-generated method stub
799 public int getAccessibleIndex(int r
, int c
)
801 // TODO Auto-generated method stub
805 public Accessible
getAccessibleCaption()
807 // TODO Auto-generated method stub
811 public void setAccessibleCaption(Accessible caption
)
813 // TODO Auto-generated method stub
817 public Accessible
getAccessibleSummary()
819 // TODO Auto-generated method stub
823 public void setAccessibleSummary(Accessible summary
)
825 // TODO Auto-generated method stub
829 public int getAccessibleRowCount()
831 // TODO Auto-generated method stub
835 public int getAccessibleColumnCount()
837 // TODO Auto-generated method stub
841 public Accessible
getAccessibleAt(int r
, int c
)
843 // TODO Auto-generated method stub
847 public int getAccessibleRowExtentAt(int r
, int c
)
849 // TODO Auto-generated method stub
853 public int getAccessibleColumnExtentAt(int r
, int c
)
855 // TODO Auto-generated method stub
859 public AccessibleTable
getAccessibleRowHeader()
861 // TODO Auto-generated method stub
865 public void setAccessibleRowHeader(AccessibleTable header
)
867 // TODO Auto-generated method stub
871 public AccessibleTable
getAccessibleColumnHeader()
873 // TODO Auto-generated method stub
877 public void setAccessibleColumnHeader(AccessibleTable header
)
879 // TODO Auto-generated method stub
883 public Accessible
getAccessibleRowDescription(int r
)
885 // TODO Auto-generated method stub
889 public void setAccessibleRowDescription(int r
, Accessible description
)
891 // TODO Auto-generated method stub
895 public Accessible
getAccessibleColumnDescription(int c
)
897 // TODO Auto-generated method stub
901 public void setAccessibleColumnDescription(int c
, Accessible description
)
903 // TODO Auto-generated method stub
907 public boolean isAccessibleSelected(int r
, int c
)
909 // TODO Auto-generated method stub
913 public boolean isAccessibleRowSelected(int r
)
915 // TODO Auto-generated method stub
919 public boolean isAccessibleColumnSelected(int c
)
921 // TODO Auto-generated method stub
925 public int[] getSelectedAccessibleRows()
927 // TODO Auto-generated method stub
931 public int[] getSelectedAccessibleColumns()
933 // TODO Auto-generated method stub
938 * Returns the accessible row at the specified index.
940 * @param index the index for which to query the row
942 * @return the row number at the specified table index
944 public int getAccessibleRowAtIndex(int index
)
946 // TODO: Back this up by a Mauve test and update API docs accordingly.
947 return index
/ getColumnCount();
951 * Returns the accessible column at the specified index.
953 * @param index the index for which to query the column
955 * @return the column number at the specified table index
957 public int getAccessibleColumnAtIndex(int index
)
959 // TODO: Back this up by a Mauve test and update API docs accordingly.
960 return index
% getColumnCount();
964 * Returns the accessible child index at the specified column and row.
967 * @param column the column
969 * @return the index of the accessible child at the specified row and
972 public int getAccessibleIndexAt(int row
, int column
)
974 // TODO: Back this up by a Mauve test and update API docs accordingly.
975 return row
* getColumnCount() + column
;
979 * Handles property changes from the <code>TableColumn</code>s of this
980 * <code>JTable</code>.
982 * More specifically, this triggers a {@link #revalidate()} call if the
983 * preferredWidth of one of the observed columns changes.
985 class TableColumnPropertyChangeHandler
implements PropertyChangeListener
988 * Receives notification that a property of the observed TableColumns has
991 * @param ev the property change event
993 public void propertyChange(PropertyChangeEvent ev
)
995 if (ev
.getPropertyName().equals("preferredWidth"))
997 JTableHeader header
= getTableHeader();
999 // Do nothing if the table is in the resizing mode.
1000 if (header
.getResizingColumn() == null)
1002 TableColumn col
= (TableColumn
) ev
.getSource();
1003 header
.setResizingColumn(col
);
1005 header
.setResizingColumn(null);
1012 * A cell renderer for boolean values.
1014 private class BooleanCellRenderer
1015 extends DefaultTableCellRenderer
1018 * The CheckBox that is used for rendering.
1020 private final JCheckBox checkBox
= new JCheckBox();
1023 * The check box must have the text field background and be centered.
1025 private BooleanCellRenderer()
1027 // Render the checkbox identically as the text field.
1028 JTextField f
= new JTextField();
1029 checkBox
.setForeground(f
.getForeground());
1030 checkBox
.setBackground(f
.getBackground());
1031 checkBox
.setHorizontalAlignment(SwingConstants
.CENTER
);
1035 * Get the check box.
1037 JCheckBox
getCheckBox()
1043 * Returns the component that is used for rendering the value.
1045 * @param table the JTable
1046 * @param value the value of the object
1047 * @param isSelected is the cell selected?
1048 * @param hasFocus has the cell the focus?
1049 * @param row the row to render
1050 * @param column the cell to render
1052 * @return this component (the default table cell renderer)
1054 public Component
getTableCellRendererComponent(JTable table
, Object value
,
1056 boolean hasFocus
, int row
,
1059 // Null is rendered as false.
1061 checkBox
.setSelected(false);
1064 Boolean boolValue
= (Boolean
) value
;
1065 checkBox
.setSelected(boolValue
.booleanValue());
1072 * A cell renderer for Date values.
1074 private class DateCellRenderer
1075 extends DefaultTableCellRenderer
1078 * Returns the component that is used for rendering the value.
1080 * @param table the JTable
1081 * @param value the value of the object
1082 * @param isSelected is the cell selected?
1083 * @param hasFocus has the cell the focus?
1084 * @param row the row to render
1085 * @param column the cell to render
1087 * @return this component (the default table cell renderer)
1089 public Component
getTableCellRendererComponent(JTable table
, Object value
,
1091 boolean hasFocus
, int row
,
1094 super.getTableCellRendererComponent(table
, value
, isSelected
, hasFocus
,
1096 if (value
instanceof Date
)
1098 Date dateValue
= (Date
) value
;
1099 DateFormat df
= DateFormat
.getDateInstance(DateFormat
.SHORT
);
1100 setText(df
.format(dateValue
));
1107 * A cell renderer for Double values.
1109 private class DoubleCellRenderer
1110 extends DefaultTableCellRenderer
1113 * Creates a new instance of NumberCellRenderer.
1115 public DoubleCellRenderer()
1117 setHorizontalAlignment(JLabel
.RIGHT
);
1121 * Returns the component that is used for rendering the value.
1123 * @param table the JTable
1124 * @param value the value of the object
1125 * @param isSelected is the cell selected?
1126 * @param hasFocus has the cell the focus?
1127 * @param row the row to render
1128 * @param column the cell to render
1130 * @return this component (the default table cell renderer)
1132 public Component
getTableCellRendererComponent(JTable table
, Object value
,
1134 boolean hasFocus
, int row
,
1137 super.getTableCellRendererComponent(table
, value
, isSelected
, hasFocus
,
1139 if (value
instanceof Double
)
1141 Double doubleValue
= (Double
) value
;
1142 NumberFormat nf
= NumberFormat
.getInstance();
1143 setText(nf
.format(doubleValue
.doubleValue()));
1150 * A cell renderer for Float values.
1152 private class FloatCellRenderer
1153 extends DefaultTableCellRenderer
1156 * Creates a new instance of NumberCellRenderer.
1158 public FloatCellRenderer()
1160 setHorizontalAlignment(JLabel
.RIGHT
);
1164 * Returns the component that is used for rendering the value.
1166 * @param table the JTable
1167 * @param value the value of the object
1168 * @param isSelected is the cell selected?
1169 * @param hasFocus has the cell the focus?
1170 * @param row the row to render
1171 * @param column the cell to render
1173 * @return this component (the default table cell renderer)
1175 public Component
getTableCellRendererComponent(JTable table
, Object value
,
1177 boolean hasFocus
, int row
,
1180 super.getTableCellRendererComponent(table
, value
, isSelected
, hasFocus
,
1182 if (value
instanceof Float
)
1184 Float floatValue
= (Float
) value
;
1185 NumberFormat nf
= NumberFormat
.getInstance();
1186 setText(nf
.format(floatValue
.floatValue()));
1193 * A cell renderer for Number values.
1195 private class NumberCellRenderer
1196 extends DefaultTableCellRenderer
1199 * Creates a new instance of NumberCellRenderer.
1201 public NumberCellRenderer()
1203 setHorizontalAlignment(JLabel
.RIGHT
);
1208 * A cell renderer for Icon values.
1210 private class IconCellRenderer
1211 extends DefaultTableCellRenderer
1214 * Returns the component that is used for rendering the value.
1216 * @param table the JTable
1217 * @param value the value of the object
1218 * @param isSelected is the cell selected?
1219 * @param hasFocus has the cell the focus?
1220 * @param row the row to render
1221 * @param column the cell to render
1223 * @return this component (the default table cell renderer)
1225 public Component
getTableCellRendererComponent(JTable table
, Object value
,
1227 boolean hasFocus
, int row
,
1230 super.getTableCellRendererComponent(table
, value
, isSelected
, hasFocus
,
1232 if (value
instanceof Icon
)
1234 Icon iconValue
= (Icon
) value
;
1243 * The JTable text component (used in editing) always has the table
1244 * as its parent. The scrollRectToVisible must be adjusted taking the
1245 * relative component position.
1247 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
1249 private class TableTextField
extends JTextField
1252 * Create the text field without the border.
1260 * Scroll the table, making the given rectangle of this component
1261 * visible. Mind the component position with relate to the table.
1262 * With not this method overridden, the scroll pane scrolls to the
1263 * top left cornec (untranslated position of the caret) after the first
1266 public void scrollRectToVisible(Rectangle r
)
1268 // In private class we known that the rectangle data will not be
1269 // reused and we need not to clone it.
1270 r
.translate(getX(), getY());
1271 super.scrollRectToVisible(r
);
1276 private static final long serialVersionUID
= 3876025080382781659L;
1279 * This table, for referring identically name methods from inner classes.
1281 final JTable this_table
= this;
1285 * When resizing columns, do not automatically change any columns. In this
1286 * case the table should be enclosed in a {@link JScrollPane} in order to
1287 * accomodate cases in which the table size exceeds its visible area.
1289 public static final int AUTO_RESIZE_OFF
= 0;
1292 * When resizing column <code>i</code>, automatically change only the
1293 * single column <code>i+1</code> to provide or absorb excess space
1296 public static final int AUTO_RESIZE_NEXT_COLUMN
= 1;
1299 * When resizing column <code>i</code> in a table of <code>n</code>
1300 * columns, automatically change all columns in the range <code>[i+1,
1301 * n)</code>, uniformly, to provide or absorb excess space requirements.
1303 public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS
= 2;
1306 * When resizing column <code>i</code> in a table of <code>n</code>
1307 * columns, automatically change all columns in the range <code>[0,
1308 * n)</code> (with the exception of column i) uniformly, to provide or
1309 * absorb excess space requirements.
1311 public static final int AUTO_RESIZE_ALL_COLUMNS
= 4;
1314 * When resizing column <code>i</code> in a table of <code>n</code>
1315 * columns, automatically change column <code>n-1</code> (the last column
1316 * in the table) to provide or absorb excess space requirements.
1318 public static final int AUTO_RESIZE_LAST_COLUMN
= 3;
1322 * A table mapping {@link java.lang.Class} objects to
1323 * {@link TableCellEditor} objects. This table is consulted by the
1326 protected Hashtable defaultEditorsByColumnClass
;
1329 * A table mapping {@link java.lang.Class} objects to
1330 * {@link TableCellEditor} objects. This table is consulted by the
1333 protected Hashtable defaultRenderersByColumnClass
;
1336 * The column that is edited, -1 if the table is not edited currently.
1338 protected int editingColumn
;
1341 * The row that is edited, -1 if the table is not edited currently.
1343 protected int editingRow
;
1346 * The component that is used for editing.
1347 * <code>null</code> if the table is not editing currently.
1350 protected transient Component editorComp
;
1354 * Whether or not the table should automatically compute a matching
1355 * {@link TableColumnModel} and assign it to the {@link #columnModel}
1356 * property when the {@link #dataModel} property is changed.
1358 * @see #setModel(TableModel)
1359 * @see #createDefaultColumnsFromModel()
1360 * @see #setColumnModel(TableColumnModel)
1361 * @see #setAutoCreateColumnsFromModel(boolean)
1362 * @see #getAutoCreateColumnsFromModel()
1364 protected boolean autoCreateColumnsFromModel
;
1367 * A numeric code specifying the resizing behavior of the table. Must be
1368 * one of {@link #AUTO_RESIZE_ALL_COLUMNS} (the default), {@link
1369 * #AUTO_RESIZE_LAST_COLUMN}, {@link #AUTO_RESIZE_NEXT_COLUMN}, {@link
1370 * #AUTO_RESIZE_SUBSEQUENT_COLUMNS}, or {@link #AUTO_RESIZE_OFF}.
1373 * @see #setAutoResizeMode(int)
1374 * @see #getAutoResizeMode()
1376 protected int autoResizeMode
;
1379 * The height in pixels of any row of the table. All rows in a table are
1380 * of uniform height. This differs from column width, which varies on a
1381 * per-column basis, and is stored in the individual columns of the
1382 * {@link #columnModel}.
1384 * @see #getRowHeight()
1385 * @see #setRowHeight(int)
1386 * @see TableColumn#getWidth()
1387 * @see TableColumn#setWidth(int)
1389 protected int rowHeight
;
1392 * The height in pixels of the gap left between any two rows of the table.
1394 * @see #setRowMargin(int)
1395 * @see #getRowHeight()
1396 * @see #getIntercellSpacing()
1397 * @see #setIntercellSpacing(Dimension)
1398 * @see TableColumnModel#getColumnMargin()
1399 * @see TableColumnModel#setColumnMargin(int)
1401 protected int rowMargin
;
1404 * Whether or not the table should allow row selection. If the table
1405 * allows both row <em>and</em> column selection, it is said to allow
1406 * "cell selection". Previous versions of the JDK supported cell
1407 * selection as an independent concept, but it is now represented solely
1408 * in terms of simultaneous row and column selection.
1410 * @see TableColumnModel#getColumnSelectionAllowed()
1411 * @see #setRowSelectionAllowed(boolean)
1412 * @see #getRowSelectionAllowed()
1413 * @see #getCellSelectionEnabled()
1414 * @see #setCellSelectionEnabled(boolean)
1416 protected boolean rowSelectionAllowed
;
1419 * Obsolete. Use {@link #rowSelectionAllowed}, {@link
1420 * #getColumnSelectionAllowed}, or the combined methods {@link
1421 * #getCellSelectionEnabled} and {@link #setCellSelectionEnabled(boolean)}.
1423 protected boolean cellSelectionEnabled
;
1426 * The model for data stored in the table. Confusingly, the published API
1427 * requires that this field be called <code>dataModel</code>, despite its
1428 * property name. The table listens to its model as a {@link
1429 * TableModelListener}.
1431 * @see #tableChanged(TableModelEvent)
1432 * @see TableModel#addTableModelListener(TableModelListener)
1434 protected TableModel dataModel
;
1437 * <p>A model of various aspects of the columns of the table, <em>not
1438 * including</em> the data stored in them. The {@link TableColumnModel}
1439 * is principally concerned with holding a set of {@link TableColumn}
1440 * objects, each of which describes the display parameters of a column
1441 * and the numeric index of the column from the data model which the
1442 * column is presenting.</p>
1444 * <p>The TableColumnModel also contains a {@link ListSelectionModel} which
1445 * indicates which columns are currently selected. This selection model
1446 * works in combination with the {@link #selectionModel} of the table
1447 * itself to specify a <em>table selection</em>: a combination of row and
1448 * column selections.</p>
1450 * <p>Most application programmers do not need to work with this property
1451 * at all: setting {@link #autoCreateColumnsFromModel} will construct the
1452 * columnModel automatically, and the table acts as a facade for most of
1453 * the interesting properties of the columnModel anyways.</p>
1455 * @see #setColumnModel(TableColumnModel)
1456 * @see #getColumnModel()
1458 protected TableColumnModel columnModel
;
1461 * A model of the rows of this table which are currently selected. This
1462 * model is used in combination with the column selection model held as a
1463 * member of the {@link #columnModel} property, to represent the rows and
1464 * columns (or both: cells) of the table which are currently selected.
1466 * @see #rowSelectionAllowed
1467 * @see #setSelectionModel(ListSelectionModel)
1468 * @see #getSelectionModel()
1469 * @see TableColumnModel#getSelectionModel()
1470 * @see ListSelectionModel#addListSelectionListener(ListSelectionListener)
1472 protected ListSelectionModel selectionModel
;
1475 * The current cell editor.
1477 protected TableCellEditor cellEditor
;
1480 * Whether or not drag-and-drop is enabled on this table.
1482 * @see #setDragEnabled(boolean)
1483 * @see #getDragEnabled()
1485 private boolean dragEnabled
;
1488 * The color to paint the grid lines of the table, when either {@link
1489 * #showHorizontalLines} or {@link #showVerticalLines} is set.
1491 * @see #setGridColor(Color)
1492 * @see #getGridColor()
1494 protected Color gridColor
;
1497 * The size this table would prefer its viewport assume, if it is
1498 * contained in a {@link JScrollPane}.
1500 * @see #setPreferredScrollableViewportSize(Dimension)
1501 * @see #getPreferredScrollableViewportSize()
1503 protected Dimension preferredViewportSize
;
1506 * The color to paint the background of selected cells. Fires a property
1507 * change event with name {@link #SELECTION_BACKGROUND_CHANGED_PROPERTY}
1508 * when its value changes.
1510 * @see #setSelectionBackground(Color)
1511 * @see #getSelectionBackground()
1513 protected Color selectionBackground
;
1516 * The name carried in property change events when the {@link
1517 * #selectionBackground} property changes.
1519 private static final String SELECTION_BACKGROUND_CHANGED_PROPERTY
= "selectionBackground";
1522 * The color to paint the foreground of selected cells. Fires a property
1523 * change event with name {@link #SELECTION_FOREGROUND_CHANGED_PROPERTY}
1524 * when its value changes.
1526 * @see #setSelectionForeground(Color)
1527 * @see #getSelectionForeground()
1529 protected Color selectionForeground
;
1532 * The name carried in property change events when the
1533 * {@link #selectionForeground} property changes.
1535 private static final String SELECTION_FOREGROUND_CHANGED_PROPERTY
= "selectionForeground";
1538 * The showHorizontalLines property.
1540 protected boolean showHorizontalLines
;
1543 * The showVerticalLines property.
1545 protected boolean showVerticalLines
;
1548 * The tableHeader property.
1550 protected JTableHeader tableHeader
;
1553 * The property handler for this table's columns.
1555 TableColumnPropertyChangeHandler tableColumnPropertyChangeHandler
=
1556 new TableColumnPropertyChangeHandler();
1559 * Whether cell editors should receive keyboard focus when the table is
1562 private boolean surrendersFocusOnKeystroke
= false;
1565 * A Rectangle object to be reused in {@link #getCellRect}.
1567 private Rectangle rectCache
= new Rectangle();
1570 * Creates a new <code>JTable</code> instance.
1574 this(null, null, null);
1578 * Creates a new <code>JTable</code> instance with the given number
1579 * of rows and columns.
1581 * @param numRows an <code>int</code> value
1582 * @param numColumns an <code>int</code> value
1584 public JTable (int numRows
, int numColumns
)
1586 this(new DefaultTableModel(numRows
, numColumns
));
1590 * Creates a new <code>JTable</code> instance, storing the given data
1591 * array and heaving the given column names. To see the column names,
1592 * you must place the JTable into the {@link JScrollPane}.
1594 * @param data an <code>Object[][]</code> the table data
1595 * @param columnNames an <code>Object[]</code> the column headers
1597 public JTable(Object
[][] data
, Object
[] columnNames
)
1599 this(new DefaultTableModel(data
, columnNames
));
1603 * Creates a new <code>JTable</code> instance, using the given data model
1604 * object that provides information about the table content. The table model
1605 * object is asked for the table size, other features and also receives
1606 * notifications in the case when the table has been edited by the user.
1611 public JTable (TableModel model
)
1613 this(model
, null, null);
1617 * Creates a new <code>JTable</code> instance, using the given model object
1618 * that provides information about the table content. The table data model
1619 * object is asked for the table size, other features and also receives
1620 * notifications in the case when the table has been edited by the user. The
1621 * table column model provides more detailed control on the table column
1625 * the table data mode
1627 * the table column model
1629 public JTable (TableModel dm
, TableColumnModel cm
)
1635 * Creates a new <code>JTable</code> instance, providing data model,
1636 * column model and list selection model. The list selection model
1637 * manages the selections.
1639 * @param dm data model (manages table data)
1640 * @param cm column model (manages table columns)
1641 * @param sm list selection model (manages table selections)
1643 public JTable (TableModel dm
, TableColumnModel cm
, ListSelectionModel sm
)
1645 boolean autoCreate
= false;
1650 setColumnModel(createDefaultColumnModel());
1653 setSelectionModel(sm
== null ?
createDefaultSelectionModel() : sm
);
1654 setModel(dm
== null ?
createDefaultDataModel() : dm
);
1655 setAutoCreateColumnsFromModel(autoCreate
);
1656 initializeLocalVars();
1657 // The following four lines properly set the lead selection indices.
1658 // After this, the UI will handle the lead selection indices.
1659 // FIXME: this should probably not be necessary, if the UI is installed
1660 // before the TableModel is set then the UI will handle things on its
1661 // own, but certain variables need to be set before the UI can be installed
1662 // so we must get the correct order for all the method calls in this
1664 selectionModel
.setAnchorSelectionIndex(0);
1665 selectionModel
.setLeadSelectionIndex(0);
1666 columnModel
.getSelectionModel().setAnchorSelectionIndex(0);
1667 columnModel
.getSelectionModel().setLeadSelectionIndex(0);
1672 * Creates a new <code>JTable</code> instance that uses data and column
1673 * names, stored in {@link Vector}s.
1675 * @param data the table data
1676 * @param columnNames the table column names.
1678 public JTable(Vector data
, Vector columnNames
)
1680 this(new DefaultTableModel(data
, columnNames
));
1684 * Initialize local variables to default values.
1686 protected void initializeLocalVars()
1688 setTableHeader(createDefaultTableHeader());
1689 if (autoCreateColumnsFromModel
)
1690 createDefaultColumnsFromModel();
1691 this.columnModel
.addColumnModelListener(this);
1693 this.defaultRenderersByColumnClass
= new Hashtable();
1694 createDefaultRenderers();
1696 this.defaultEditorsByColumnClass
= new Hashtable();
1697 createDefaultEditors();
1699 this.autoResizeMode
= AUTO_RESIZE_SUBSEQUENT_COLUMNS
;
1700 this.rowHeight
= 16;
1702 this.rowSelectionAllowed
= true;
1703 // this.accessibleContext = new AccessibleJTable();
1704 this.cellEditor
= null;
1705 // COMPAT: Both Sun and IBM have drag enabled
1706 this.dragEnabled
= true;
1707 this.preferredViewportSize
= new Dimension(450,400);
1708 this.showHorizontalLines
= true;
1709 this.showVerticalLines
= true;
1710 this.editingColumn
= -1;
1711 this.editingRow
= -1;
1712 setIntercellSpacing(new Dimension(1,1));
1716 * Add the new table column. The table column class allows to specify column
1717 * features more precisely, setting the preferred width, column data type
1718 * (column class) and table headers.
1720 * There is no need the add columns to the table if the default column
1721 * handling is sufficient.
1724 * the new column to add.
1726 public void addColumn(TableColumn column
)
1728 if (column
.getHeaderValue() == null)
1730 String name
= dataModel
.getColumnName(column
.getModelIndex());
1731 column
.setHeaderValue(name
);
1734 columnModel
.addColumn(column
);
1735 column
.addPropertyChangeListener(tableColumnPropertyChangeHandler
);
1739 * Create the default editors for this table. The default method creates
1740 * the editor for Booleans.
1742 * Other fields are edited as strings at the moment.
1744 protected void createDefaultEditors()
1746 JCheckBox box
= new BooleanCellRenderer().getCheckBox();
1747 setDefaultEditor(Boolean
.class, new DefaultCellEditor(box
));
1751 * Create the default renderers for this table. The default method creates
1752 * renderers for Boolean, Number, Double, Date, Icon and ImageIcon.
1755 protected void createDefaultRenderers()
1757 setDefaultRenderer(Boolean
.class, new BooleanCellRenderer());
1758 setDefaultRenderer(Number
.class, new NumberCellRenderer());
1759 setDefaultRenderer(Double
.class, new DoubleCellRenderer());
1760 setDefaultRenderer(Double
.class, new FloatCellRenderer());
1761 setDefaultRenderer(Date
.class, new DateCellRenderer());
1762 setDefaultRenderer(Icon
.class, new IconCellRenderer());
1763 setDefaultRenderer(ImageIcon
.class, new IconCellRenderer());
1767 * @deprecated 1.0.2, replaced by <code>new JScrollPane(JTable)</code>
1769 public static JScrollPane
createScrollPaneForTable(JTable table
)
1771 return new JScrollPane(table
);
1775 * Create the default table column model that is used if the user-defined
1776 * column model is not provided. The default method creates
1777 * {@link DefaultTableColumnModel}.
1779 * @return the created table column model.
1781 protected TableColumnModel
createDefaultColumnModel()
1783 return new DefaultTableColumnModel();
1787 * Create the default table data model that is used if the user-defined
1788 * data model is not provided. The default method creates
1789 * {@link DefaultTableModel}.
1791 * @return the created table data model.
1793 protected TableModel
createDefaultDataModel()
1795 return new DefaultTableModel();
1799 * Create the default table selection model that is used if the user-defined
1800 * selection model is not provided. The default method creates
1801 * {@link DefaultListSelectionModel}.
1803 * @return the created table data model.
1805 protected ListSelectionModel
createDefaultSelectionModel()
1807 return new DefaultListSelectionModel();
1811 * Create the default table header, if the user - defined table header is not
1814 * @return the default table header.
1816 protected JTableHeader
createDefaultTableHeader()
1818 return new JTableHeader(columnModel
);
1822 * Invoked when the column is added. Revalidates and repains the table.
1824 public void columnAdded (TableColumnModelEvent event
)
1831 * Invoked when the column margin is changed.
1832 * Revalidates and repains the table.
1834 public void columnMarginChanged (ChangeEvent event
)
1841 * Invoked when the column is moved. Revalidates and repains the table.
1843 public void columnMoved (TableColumnModelEvent event
)
1850 * Invoked when the column is removed. Revalidates and repains the table.
1852 public void columnRemoved (TableColumnModelEvent event
)
1859 * Invoked when the the column selection changes.
1861 public void columnSelectionChanged (ListSelectionEvent event
)
1867 * Invoked when the editing is cancelled.
1869 public void editingCanceled (ChangeEvent event
)
1871 if (editorComp
!=null)
1874 repaint(editorComp
.getBounds());
1880 * Finish the current editing session and update the table with the
1881 * new value by calling {@link #setValueAt}.
1883 * @param event the change event
1885 public void editingStopped (ChangeEvent event
)
1887 if (editorComp
!=null)
1890 setValueAt(cellEditor
.getCellEditorValue(), editingRow
, editingColumn
);
1891 repaint(editorComp
.getBounds());
1894 requestFocusInWindow();
1898 * Invoked when the table changes.
1899 * <code>null</code> means everything changed.
1901 public void tableChanged (TableModelEvent event
)
1903 // update the column model from the table model if the structure has
1904 // changed and the flag autoCreateColumnsFromModel is set
1905 if ((event
== null || (event
.getFirstRow() == TableModelEvent
.HEADER_ROW
))
1906 && autoCreateColumnsFromModel
)
1907 createDefaultColumnsFromModel();
1909 // If the structure changes, we need to revalidate, since that might
1910 // affect the size parameters of the JTable. Otherwise we only need
1911 // to perform a repaint to update the view.
1912 if (event
== null || event
.getType() == TableModelEvent
.INSERT
)
1914 if (event
== null || event
.getType() == TableModelEvent
.DELETE
)
1916 if (dataModel
.getRowCount() == 0)
1924 * Invoked when another table row is selected.
1926 public void valueChanged (ListSelectionEvent event
)
1932 * Returns index of the column that contains specified point
1933 * or -1 if this table doesn't contain this point.
1935 * @param point point to identify the column
1936 * @return index of the column that contains specified point or
1937 * -1 if this table doesn't contain this point.
1939 public int columnAtPoint(Point point
)
1943 int ncols
= getColumnCount();
1944 Dimension gap
= getIntercellSpacing();
1945 TableColumnModel cols
= getColumnModel();
1948 for (int i
= 0; i
< ncols
; ++i
)
1950 int width
= cols
.getColumn(i
).getWidth()
1951 + (gap
== null ?
0 : gap
.width
);
1952 if (0 <= x
&& x
< width
)
1961 * Returns index of the row that contains specified point or -1 if this table
1962 * doesn't contain this point.
1965 * point to identify the row
1966 * @return index of the row that contains specified point or -1 if this table
1967 * doesn't contain this point.
1969 public int rowAtPoint(Point point
)
1973 int nrows
= getRowCount();
1974 int height
= getRowHeight() + getRowMargin();
1978 if (r
< 0 || r
>= nrows
)
1988 * Calculate the visible rectangle for a particular row and column. The
1989 * row and column are specified in visual terms; the column may not match
1990 * the {@link #dataModel} column.
1992 * @param row the visible row to get the cell rectangle of
1994 * @param column the visible column to get the cell rectangle of, which may
1995 * differ from the {@link #dataModel} column
1997 * @param includeSpacing whether or not to include the cell margins in the
1998 * resulting cell. If <code>false</code>, the result will only contain the
1999 * inner area of the target cell, not including its margins.
2001 * @return a rectangle enclosing the specified cell
2003 public Rectangle
getCellRect(int row
,
2005 boolean includeSpacing
)
2007 // moveToCellBeingEdited expects the cached value and clones it.
2008 // If the caching would be removed later, uplate moveToCellBeingEdited
2010 int height
= getRowHeight(row
);
2011 int width
= columnModel
.getColumn(column
).getWidth();
2012 int x_gap
= columnModel
.getColumnMargin();
2013 int y_gap
= rowMargin
;
2015 column
= Math
.max(0, Math
.min(column
, getColumnCount() - 1));
2016 row
= Math
.max(0, Math
.min(row
, getRowCount() - 1));
2019 int y
= (height
+ y_gap
) * row
;
2021 for (int i
= 0; i
< column
; ++i
)
2022 x
+= columnModel
.getColumn(i
).getWidth();
2025 rectCache
.setBounds(x
, y
, width
, height
+y_gap
);
2027 rectCache
.setBounds(x
, y
, width
- x_gap
, height
);
2031 public void clearSelection()
2033 selectionModel
.clearSelection();
2034 getColumnModel().getSelectionModel().clearSelection();
2038 * Get the value of the selectedRow property by delegation to
2039 * the {@link ListSelectionModel#getMinSelectionIndex} method of the
2040 * {@link #selectionModel} field.
2042 * @return The current value of the selectedRow property
2044 public int getSelectedRow ()
2046 return selectionModel
.getMinSelectionIndex();
2050 * Get the value of the {@link #selectionModel} property.
2052 * @return The current value of the property
2054 public ListSelectionModel
getSelectionModel()
2056 //Neither Sun nor IBM returns null if rowSelection not allowed
2057 return selectionModel
;
2060 public int getScrollableBlockIncrement(Rectangle visibleRect
, int orientation
, int direction
)
2062 if (orientation
== SwingConstants
.VERTICAL
)
2063 return visibleRect
.height
* direction
;
2065 return visibleRect
.width
* direction
;
2069 * Get the value of the <code>scrollableTracksViewportHeight</code> property.
2071 * @return The constant value <code>false</code>
2073 public boolean getScrollableTracksViewportHeight()
2079 * Get the value of the <code>scrollableTracksViewportWidth</code> property.
2081 * @return <code>true</code> unless the {@link #autoResizeMode} property is
2082 * <code>AUTO_RESIZE_OFF</code>
2084 public boolean getScrollableTracksViewportWidth()
2086 if (autoResizeMode
== AUTO_RESIZE_OFF
)
2092 public int getScrollableUnitIncrement(Rectangle visibleRect
, int orientation
, int direction
)
2094 // FIXME: I don't exactly know what sun does here. in both cases they
2095 // pick values which do *not* simply expose the next cell in a given
2096 // scroll direction.
2098 if (orientation
== SwingConstants
.VERTICAL
)
2099 return direction
* rowHeight
;
2103 for (int i
= 0; i
< getColumnCount(); ++i
)
2104 sum
+= columnModel
.getColumn(0).getWidth();
2105 int inc
= getColumnCount() == 0 ?
10 : sum
/ getColumnCount();
2106 return direction
* inc
;
2112 * Get the cell editor, suitable for editing the given cell. The default
2113 * method requests the editor from the column model. If the column model does
2114 * not provide the editor, the call is forwarded to the
2115 * {@link #getDefaultEditor(Class)} with the parameter, obtained from
2116 * {@link TableModel#getColumnClass(int)}.
2118 * @param row the cell row
2119 * @param column the cell column
2120 * @return the editor to edit that cell
2122 public TableCellEditor
getCellEditor(int row
, int column
)
2124 TableCellEditor editor
= columnModel
.getColumn(column
).getCellEditor();
2128 int mcolumn
= convertColumnIndexToModel(column
);
2129 editor
= getDefaultEditor(dataModel
.getColumnClass(mcolumn
));
2136 * Get the default editor for editing values of the given type
2137 * (String, Boolean and so on).
2139 * @param columnClass the class of the value that will be edited.
2141 * @return the editor, suitable for editing this data type
2143 public TableCellEditor
getDefaultEditor(Class columnClass
)
2145 if (defaultEditorsByColumnClass
.containsKey(columnClass
))
2146 return (TableCellEditor
) defaultEditorsByColumnClass
.get(columnClass
);
2149 JTextField t
= new TableTextField();
2150 TableCellEditor r
= new DefaultCellEditor(t
);
2151 defaultEditorsByColumnClass
.put(columnClass
, r
);
2157 * Get the cell renderer for rendering the given cell.
2159 * @param row the cell row
2160 * @param column the cell column
2161 * @return the cell renderer to render that cell.
2163 public TableCellRenderer
getCellRenderer(int row
, int column
)
2165 TableCellRenderer renderer
= columnModel
.getColumn(column
).getCellRenderer();
2166 if (renderer
== null)
2168 int mcolumn
= convertColumnIndexToModel(column
);
2169 renderer
= getDefaultRenderer(dataModel
.getColumnClass(mcolumn
));
2175 * Set default renderer for rendering the given data type.
2177 * @param columnClass the data type (String, Boolean and so on) that must be
2179 * @param rend the renderer that will rend this data type
2181 public void setDefaultRenderer(Class columnClass
, TableCellRenderer rend
)
2183 defaultRenderersByColumnClass
.put(columnClass
, rend
);
2187 * Get the default renderer for rendering the given data type.
2189 * @param columnClass the data that must be rendered
2191 * @return the appropriate defauld renderer for rendering that data type.
2193 public TableCellRenderer
getDefaultRenderer(Class columnClass
)
2195 if (defaultRenderersByColumnClass
.containsKey(columnClass
))
2196 return (TableCellRenderer
) defaultRenderersByColumnClass
.get(columnClass
);
2199 TableCellRenderer r
= new DefaultTableCellRenderer();
2200 defaultRenderersByColumnClass
.put(columnClass
, r
);
2206 * Convert the table model index into the table column number.
2207 * The model number need not match the real column position. The columns
2208 * may be rearranged by the user with mouse at any time by dragging the
2211 * @param vc the column number (0=first).
2213 * @return the table column model index of this column.
2215 * @see TableColumn#getModelIndex()
2217 public int convertColumnIndexToModel(int vc
)
2222 return columnModel
.getColumn(vc
).getModelIndex();
2226 * Convert the table column number to the table column model index.
2227 * The model number need not match the real column position. The columns
2228 * may be rearranged by the user with mouse at any time by dragging the
2231 * @param mc the table column index (0=first).
2233 * @return the table column number in the model
2235 * @see TableColumn#getModelIndex()
2237 public int convertColumnIndexToView(int mc
)
2241 int ncols
= getColumnCount();
2242 for (int vc
= 0; vc
< ncols
; ++vc
)
2244 if (columnModel
.getColumn(vc
).getModelIndex() == mc
)
2251 * Prepare the renderer for rendering the given cell.
2253 * @param renderer the renderer being prepared
2254 * @param row the row of the cell being rendered
2255 * @param column the column of the cell being rendered
2257 * @return the component which .paint() method will paint the cell.
2259 public Component
prepareRenderer(TableCellRenderer renderer
,
2264 boolean rowSelAllowed
= getRowSelectionAllowed();
2265 boolean colSelAllowed
= getColumnSelectionAllowed();
2266 boolean isSel
= false;
2267 if (rowSelAllowed
&& colSelAllowed
|| !rowSelAllowed
&& !colSelAllowed
)
2268 isSel
= isCellSelected(row
, column
);
2270 isSel
= isRowSelected(row
) && getRowSelectionAllowed()
2271 || isColumnSelected(column
) && getColumnSelectionAllowed();
2273 // Determine the focused cell. The focused cell is the cell at the
2274 // leadSelectionIndices of the row and column selection model.
2275 ListSelectionModel rowSel
= getSelectionModel();
2276 ListSelectionModel colSel
= getColumnModel().getSelectionModel();
2277 boolean hasFocus
= hasFocus() && isEnabled()
2278 && rowSel
.getLeadSelectionIndex() == row
2279 && colSel
.getLeadSelectionIndex() == column
;
2281 return renderer
.getTableCellRendererComponent(this,
2282 dataModel
.getValueAt(row
,
2283 convertColumnIndexToModel(column
)),
2291 * Get the value of the {@link #autoCreateColumnsFromModel} property.
2293 * @return The current value of the property
2295 public boolean getAutoCreateColumnsFromModel()
2297 return autoCreateColumnsFromModel
;
2301 * Get the value of the {@link #autoResizeMode} property.
2303 * @return The current value of the property
2305 public int getAutoResizeMode()
2307 return autoResizeMode
;
2311 * Get the value of the {@link #rowHeight} property.
2313 * @return The current value of the property
2315 public int getRowHeight()
2321 * Get the height of the specified row.
2323 * @param row the row whose height to return
2325 public int getRowHeight(int row
)
2327 // FIXME: return the height of the specified row
2328 // which may be different from the general rowHeight
2334 * Get the value of the {@link #rowMargin} property.
2336 * @return The current value of the property
2338 public int getRowMargin()
2344 * Get the value of the {@link #rowSelectionAllowed} property.
2346 * @return The current value of the property
2348 public boolean getRowSelectionAllowed()
2350 return rowSelectionAllowed
;
2354 * Get the value of the {@link #cellSelectionEnabled} property.
2356 * @return The current value of the property
2358 public boolean getCellSelectionEnabled()
2360 return getColumnSelectionAllowed() && getRowSelectionAllowed();
2364 * Get the value of the {@link #dataModel} property.
2366 * @return The current value of the property
2368 public TableModel
getModel()
2374 * Get the value of the <code>columnCount</code> property by
2375 * delegation to the @{link #columnModel} field.
2377 * @return The current value of the columnCount property
2379 public int getColumnCount()
2381 return columnModel
.getColumnCount();
2385 * Get the value of the <code>rowCount</code> property by
2386 * delegation to the @{link #dataModel} field.
2388 * @return The current value of the rowCount property
2390 public int getRowCount()
2392 return dataModel
.getRowCount();
2396 * Get the value of the {@link #columnModel} property.
2398 * @return The current value of the property
2400 public TableColumnModel
getColumnModel()
2406 * Get the value of the <code>selectedColumn</code> property by
2407 * delegation to the @{link #columnModel} field.
2409 * @return The current value of the selectedColumn property
2411 public int getSelectedColumn()
2413 return columnModel
.getSelectionModel().getMinSelectionIndex();
2416 private static int countSelections(ListSelectionModel lsm
)
2418 int lo
= lsm
.getMinSelectionIndex();
2419 int hi
= lsm
.getMaxSelectionIndex();
2421 if (lo
!= -1 && hi
!= -1)
2423 switch (lsm
.getSelectionMode())
2425 case ListSelectionModel
.SINGLE_SELECTION
:
2429 case ListSelectionModel
.SINGLE_INTERVAL_SELECTION
:
2433 case ListSelectionModel
.MULTIPLE_INTERVAL_SELECTION
:
2434 for (int i
= lo
; i
<= hi
; ++i
)
2435 if (lsm
.isSelectedIndex(i
))
2443 private static int[] getSelections(ListSelectionModel lsm
)
2445 int sz
= countSelections(lsm
);
2446 int [] ret
= new int[sz
];
2448 int lo
= lsm
.getMinSelectionIndex();
2449 int hi
= lsm
.getMaxSelectionIndex();
2451 if (lo
!= -1 && hi
!= -1)
2453 switch (lsm
.getSelectionMode())
2455 case ListSelectionModel
.SINGLE_SELECTION
:
2459 case ListSelectionModel
.SINGLE_INTERVAL_SELECTION
:
2460 for (int i
= lo
; i
<= hi
; ++i
)
2464 case ListSelectionModel
.MULTIPLE_INTERVAL_SELECTION
:
2465 for (int i
= lo
; i
<= hi
; ++i
)
2466 if (lsm
.isSelectedIndex(i
))
2475 * Get the value of the <code>selectedColumnCount</code> property by
2476 * delegation to the @{link #columnModel} field.
2478 * @return The current value of the selectedColumnCount property
2480 public int getSelectedColumnCount()
2482 return countSelections(columnModel
.getSelectionModel());
2486 * Get the value of the <code>selectedColumns</code> property by
2487 * delegation to the @{link #columnModel} field.
2489 * @return The current value of the selectedColumns property
2491 public int[] getSelectedColumns()
2493 return getSelections(columnModel
.getSelectionModel());
2497 * Get the value of the <code>columnSelectionAllowed</code> property.
2499 * @return The current value of the columnSelectionAllowed property
2501 public boolean getColumnSelectionAllowed()
2503 return getColumnModel().getColumnSelectionAllowed();
2507 * Get the value of the <code>selectedRowCount</code> property by
2508 * delegation to the @{link #selectionModel} field.
2510 * @return The current value of the selectedRowCount property
2512 public int getSelectedRowCount()
2514 return countSelections(selectionModel
);
2518 * Get the value of the <code>selectedRows</code> property by
2519 * delegation to the @{link #selectionModel} field.
2521 * @return The current value of the selectedRows property
2523 public int[] getSelectedRows()
2525 return getSelections(selectionModel
);
2529 * Get the value of the {@link #accessibleContext} property.
2531 * @return The current value of the property
2533 public AccessibleContext
getAccessibleContext()
2535 return accessibleContext
;
2539 * Get the value of the {@link #cellEditor} property.
2541 * @return The current value of the property
2543 public TableCellEditor
getCellEditor()
2549 * Get the value of the {@link #dragEnabled} property.
2551 * @return The current value of the property
2553 public boolean getDragEnabled()
2559 * Get the value of the {@link #gridColor} property.
2561 * @return The current value of the property
2563 public Color
getGridColor()
2569 * Get the value of the <code>intercellSpacing</code> property.
2571 * @return The current value of the property
2573 public Dimension
getIntercellSpacing()
2575 return new Dimension(columnModel
.getColumnMargin(), rowMargin
);
2579 * Get the value of the {@link #preferredViewportSize} property.
2581 * @return The current value of the property
2583 public Dimension
getPreferredScrollableViewportSize()
2585 return preferredViewportSize
;
2589 * Get the value of the {@link #selectionBackground} property.
2591 * @return The current value of the property
2593 public Color
getSelectionBackground()
2595 return selectionBackground
;
2599 * Get the value of the {@link #selectionForeground} property.
2601 * @return The current value of the property
2603 public Color
getSelectionForeground()
2605 return selectionForeground
;
2609 * Get the value of the {@link #showHorizontalLines} property.
2611 * @return The current value of the property
2613 public boolean getShowHorizontalLines()
2615 return showHorizontalLines
;
2619 * Get the value of the {@link #showVerticalLines} property.
2621 * @return The current value of the property
2623 public boolean getShowVerticalLines()
2625 return showVerticalLines
;
2629 * Get the value of the {@link #tableHeader} property.
2631 * @return The current value of the property
2633 public JTableHeader
getTableHeader()
2639 * Removes specified column from displayable columns of this table.
2641 * @param column column to removed
2643 public void removeColumn(TableColumn column
)
2645 columnModel
.removeColumn(column
);
2649 * Moves column at the specified index to new given location.
2651 * @param column index of the column to move
2652 * @param targetColumn index specifying new location of the column
2654 public void moveColumn(int column
,int targetColumn
)
2656 columnModel
.moveColumn(column
, targetColumn
);
2660 * Set the value of the {@link #autoCreateColumnsFromModel} flag. If the
2661 * flag changes from <code>false</code> to <code>true</code>, the
2662 * {@link #createDefaultColumnsFromModel()} method is called.
2664 * @param autoCreate the new value of the flag.
2666 public void setAutoCreateColumnsFromModel(boolean autoCreate
)
2668 if (autoCreateColumnsFromModel
!= autoCreate
)
2670 autoCreateColumnsFromModel
= autoCreate
;
2672 createDefaultColumnsFromModel();
2677 * Set the value of the {@link #autoResizeMode} property.
2679 * @param a The new value of the autoResizeMode property
2681 public void setAutoResizeMode(int a
)
2689 * Set the value of the {@link #rowHeight} property.
2691 * @param r The new value of the rowHeight property
2693 public void setRowHeight(int r
)
2696 throw new IllegalArgumentException();
2704 * Sets the value of the rowHeight property for the specified
2707 * @param rh is the new rowHeight
2708 * @param row is the row to change the rowHeight of
2710 public void setRowHeight(int row
, int rh
)
2713 // FIXME: not implemented
2717 * Set the value of the {@link #rowMargin} property.
2719 * @param r The new value of the rowMargin property
2721 public void setRowMargin(int r
)
2729 * Set the value of the {@link #rowSelectionAllowed} property.
2731 * @param r The new value of the rowSelectionAllowed property
2733 public void setRowSelectionAllowed(boolean r
)
2735 rowSelectionAllowed
= r
;
2740 * Set the value of the {@link #cellSelectionEnabled} property.
2742 * @param c The new value of the cellSelectionEnabled property
2744 public void setCellSelectionEnabled(boolean c
)
2746 setColumnSelectionAllowed(c
);
2747 setRowSelectionAllowed(c
);
2748 // for backward-compatibility sake:
2749 cellSelectionEnabled
= true;
2753 * <p>Set the value of the {@link #dataModel} property.</p>
2755 * <p>Unregister <code>this</code> as a {@link TableModelListener} from
2756 * previous {@link #dataModel} and register it with new parameter
2757 * <code>m</code>.</p>
2759 * @param m The new value of the model property
2761 public void setModel(TableModel m
)
2763 // Throw exception is m is null.
2765 throw new IllegalArgumentException();
2767 // Don't do anything if setting the current model again.
2771 TableModel oldModel
= dataModel
;
2773 // Remove table as TableModelListener from old model.
2774 if (dataModel
!= null)
2775 dataModel
.removeTableModelListener(this);
2782 // Add table as TableModelListener to new model.
2783 dataModel
.addTableModelListener(this);
2785 // Automatically create columns.
2786 if (autoCreateColumnsFromModel
)
2787 createDefaultColumnsFromModel();
2790 // This property is bound, so we fire a property change event.
2791 firePropertyChange("model", oldModel
, dataModel
);
2799 * <p>Set the value of the {@link #columnModel} property.</p>
2801 * <p>Unregister <code>this</code> as a {@link TableColumnModelListener}
2802 * from previous {@link #columnModel} and register it with new parameter
2803 * <code>c</code>.</p>
2805 * @param c The new value of the columnModel property
2807 public void setColumnModel(TableColumnModel c
)
2810 throw new IllegalArgumentException();
2811 TableColumnModel tmp
= columnModel
;
2813 tmp
.removeColumnModelListener(this);
2815 c
.addColumnModelListener(this);
2817 if (dataModel
!= null && columnModel
!= null)
2819 int ncols
= getColumnCount();
2821 for (int i
= 0; i
< ncols
; ++i
)
2823 column
= columnModel
.getColumn(i
);
2824 if (column
.getHeaderValue()==null)
2825 column
.setHeaderValue(dataModel
.getColumnName(i
));
2829 // according to Sun's spec we also have to set the tableHeader's
2830 // column model here
2831 if (tableHeader
!= null)
2832 tableHeader
.setColumnModel(c
);
2839 * Set the value of the <code>columnSelectionAllowed</code> property.
2841 * @param c The new value of the property
2843 public void setColumnSelectionAllowed(boolean c
)
2845 getColumnModel().setColumnSelectionAllowed(c
);
2850 * <p>Set the value of the {@link #selectionModel} property.</p>
2852 * <p>Unregister <code>this</code> as a {@link ListSelectionListener}
2853 * from previous {@link #selectionModel} and register it with new
2854 * parameter <code>s</code>.</p>
2856 * @param s The new value of the selectionModel property
2858 public void setSelectionModel(ListSelectionModel s
)
2861 throw new IllegalArgumentException();
2862 ListSelectionModel tmp
= selectionModel
;
2864 tmp
.removeListSelectionListener(this);
2866 s
.addListSelectionListener(this);
2871 * Set the value of the <code>selectionMode</code> property by
2872 * delegation to the {@link #selectionModel} field. The same selection
2873 * mode is set for row and column selection models.
2875 * @param s The new value of the property
2877 public void setSelectionMode(int s
)
2879 selectionModel
.setSelectionMode(s
);
2880 columnModel
.getSelectionModel().setSelectionMode(s
);
2886 * <p>Set the value of the {@link #cellEditor} property.</p>
2888 * <p>Unregister <code>this</code> as a {@link CellEditorListener} from
2889 * previous {@link #cellEditor} and register it with new parameter
2890 * <code>c</code>.</p>
2892 * @param c The new value of the cellEditor property
2894 public void setCellEditor(TableCellEditor c
)
2896 TableCellEditor tmp
= cellEditor
;
2898 tmp
.removeCellEditorListener(this);
2900 c
.addCellEditorListener(this);
2905 * Set the value of the {@link #dragEnabled} property.
2907 * @param d The new value of the dragEnabled property
2909 public void setDragEnabled(boolean d
)
2915 * Set the value of the {@link #gridColor} property.
2917 * @param g The new value of the gridColor property
2919 public void setGridColor(Color g
)
2926 * Set the value of the <code>intercellSpacing</code> property.
2928 * @param i The new value of the intercellSpacing property
2930 public void setIntercellSpacing(Dimension i
)
2932 rowMargin
= i
.height
;
2933 columnModel
.setColumnMargin(i
.width
);
2938 * Set the value of the {@link #preferredViewportSize} property.
2940 * @param p The new value of the preferredViewportSize property
2942 public void setPreferredScrollableViewportSize(Dimension p
)
2944 preferredViewportSize
= p
;
2950 * <p>Set the value of the {@link #selectionBackground} property.</p>
2952 * <p>Fire a PropertyChangeEvent with name {@link
2953 * #SELECTION_BACKGROUND_CHANGED_PROPERTY} to registered listeners, if
2954 * selectionBackground changed.</p>
2956 * @param s The new value of the selectionBackground property
2958 public void setSelectionBackground(Color s
)
2960 Color tmp
= selectionBackground
;
2961 selectionBackground
= s
;
2962 if (((tmp
== null && s
!= null)
2963 || (s
== null && tmp
!= null)
2964 || (tmp
!= null && s
!= null && !tmp
.equals(s
))))
2965 firePropertyChange(SELECTION_BACKGROUND_CHANGED_PROPERTY
, tmp
, s
);
2970 * <p>Set the value of the {@link #selectionForeground} property.</p>
2972 * <p>Fire a PropertyChangeEvent with name {@link
2973 * #SELECTION_FOREGROUND_CHANGED_PROPERTY} to registered listeners, if
2974 * selectionForeground changed.</p>
2976 * @param s The new value of the selectionForeground property
2978 public void setSelectionForeground(Color s
)
2980 Color tmp
= selectionForeground
;
2981 selectionForeground
= s
;
2982 if (((tmp
== null && s
!= null)
2983 || (s
== null && tmp
!= null)
2984 || (tmp
!= null && s
!= null && !tmp
.equals(s
))))
2985 firePropertyChange(SELECTION_FOREGROUND_CHANGED_PROPERTY
, tmp
, s
);
2990 * Set the value of the <code>showGrid</code> property.
2992 * @param s The new value of the showGrid property
2994 public void setShowGrid(boolean s
)
2996 setShowVerticalLines(s
);
2997 setShowHorizontalLines(s
);
3001 * Set the value of the {@link #showHorizontalLines} property.
3003 * @param s The new value of the showHorizontalLines property
3005 public void setShowHorizontalLines(boolean s
)
3007 showHorizontalLines
= s
;
3012 * Set the value of the {@link #showVerticalLines} property.
3014 * @param s The new value of the showVerticalLines property
3016 public void setShowVerticalLines(boolean s
)
3018 showVerticalLines
= s
;
3023 * Set the value of the {@link #tableHeader} property.
3025 * @param t The new value of the tableHeader property
3027 public void setTableHeader(JTableHeader t
)
3029 if (tableHeader
!= null)
3030 tableHeader
.setTable(null);
3032 if (tableHeader
!= null)
3033 tableHeader
.setTable(this);
3038 protected void configureEnclosingScrollPane()
3040 JScrollPane jsp
= (JScrollPane
) SwingUtilities
.getAncestorOfClass(JScrollPane
.class, this);
3041 if (jsp
!= null && tableHeader
!= null)
3043 jsp
.setColumnHeaderView(tableHeader
);
3047 protected void unconfigureEnclosingScrollPane()
3049 JScrollPane jsp
= (JScrollPane
) SwingUtilities
.getAncestorOfClass(JScrollPane
.class, this);
3052 jsp
.setColumnHeaderView(null);
3057 public void addNotify()
3060 configureEnclosingScrollPane();
3063 public void removeNotify()
3066 unconfigureEnclosingScrollPane();
3071 * This distributes the superfluous width in a table evenly on its columns.
3073 * The implementation used here is different to that one described in
3074 * the JavaDocs. It is much simpler, and seems to work very well.
3076 * TODO: correctly implement the algorithm described in the JavaDoc
3078 private void distributeSpill(TableColumn
[] cols
, int spill
)
3080 int average
= spill
/ cols
.length
;
3081 for (int i
= 0; i
< cols
.length
; i
++)
3083 if (cols
[i
] != null)
3084 cols
[i
].setWidth(cols
[i
].getPreferredWidth() + average
);
3089 * This distributes the superfluous width in a table, setting the width of the
3090 * column being resized strictly to its preferred width.
3092 private void distributeSpillResizing(TableColumn
[] cols
, int spill
,
3093 TableColumn resizeIt
)
3096 if (cols
.length
!= 1)
3097 average
= spill
/ (cols
.length
-1);
3098 for (int i
= 0; i
< cols
.length
; i
++)
3100 if (cols
[i
] != null && !cols
[i
].equals(resizeIt
))
3101 cols
[i
].setWidth(cols
[i
].getPreferredWidth() + average
);
3103 resizeIt
.setWidth(resizeIt
.getPreferredWidth());
3107 * Set the widths of all columns, taking they preferred widths into
3108 * consideration. The excess space, if any, will be distrubuted between
3109 * all columns. This method also handles special cases when one of the
3110 * collumns is currently being resized.
3112 * @see TableColumn#setPreferredWidth(int)
3114 public void doLayout()
3116 TableColumn resizingColumn
= null;
3118 int ncols
= getColumnCount();
3125 if (tableHeader
!= null)
3126 resizingColumn
= tableHeader
.getResizingColumn();
3128 for (int i
= 0; i
< ncols
; ++i
)
3130 TableColumn col
= columnModel
.getColumn(i
);
3131 int p
= col
.getPreferredWidth();
3133 if (resizingColumn
== col
)
3137 int spill
= getWidth() - prefSum
;
3139 if (resizingColumn
!= null)
3142 TableColumn
[] cols
;
3144 switch (getAutoResizeMode())
3146 case AUTO_RESIZE_LAST_COLUMN
:
3147 col
= columnModel
.getColumn(ncols
-1);
3148 col
.setWidth(col
.getPreferredWidth() + spill
);
3151 case AUTO_RESIZE_NEXT_COLUMN
:
3152 col
= columnModel
.getColumn(ncols
-1);
3153 col
.setWidth(col
.getPreferredWidth() + spill
);
3156 case AUTO_RESIZE_ALL_COLUMNS
:
3157 cols
= new TableColumn
[ncols
];
3158 for (int i
= 0; i
< ncols
; ++i
)
3159 cols
[i
] = columnModel
.getColumn(i
);
3160 distributeSpillResizing(cols
, spill
, resizingColumn
);
3163 case AUTO_RESIZE_SUBSEQUENT_COLUMNS
:
3165 // Subtract the width of the non-resized columns from the spill.
3169 for (int i
= 0; i
< rCol
; i
++)
3171 column
= columnModel
.getColumn(i
);
3172 w
+= column
.getWidth();
3173 wp
+= column
.getPreferredWidth();
3176 // The number of columns right from the column being resized.
3177 int n
= ncols
-rCol
-1;
3180 // If there are any columns on the right sied to resize.
3181 spill
= (getWidth()-w
) - (prefSum
-wp
);
3182 int average
= spill
/ n
;
3184 // For all columns right from the column being resized:
3185 for (int i
= rCol
+1; i
< ncols
; i
++)
3187 column
= columnModel
.getColumn(i
);
3188 column
.setWidth(column
.getPreferredWidth() + average
);
3191 resizingColumn
.setWidth(resizingColumn
.getPreferredWidth());
3194 case AUTO_RESIZE_OFF
:
3196 int prefWidth
= resizingColumn
.getPreferredWidth();
3197 resizingColumn
.setWidth(prefWidth
);
3202 TableColumn
[] cols
= new TableColumn
[ncols
];
3203 for (int i
= 0; i
< ncols
; ++i
)
3204 cols
[i
] = columnModel
.getColumn(i
);
3205 distributeSpill(cols
, spill
);
3208 if (editorComp
!=null)
3209 moveToCellBeingEdited(editorComp
);
3211 // Repaint fixes the invalid view after the first keystroke if the cell
3212 // editing is started immediately after the program start or cell
3215 if (tableHeader
!=null)
3216 tableHeader
.repaint();
3220 * @deprecated Replaced by <code>doLayout()</code>
3222 public void sizeColumnsToFit(boolean lastColumnOnly
)
3228 * Obsolete since JDK 1.4. Please use <code>doLayout()</code>.
3230 public void sizeColumnsToFit(int resizingColumn
)
3235 public String
getUIClassID()
3241 * This method returns the table's UI delegate.
3243 * @return The table's UI delegate.
3245 public TableUI
getUI()
3247 return (TableUI
) ui
;
3251 * This method sets the table's UI delegate.
3253 * @param ui The table's UI delegate.
3255 public void setUI(TableUI ui
)
3260 public void updateUI()
3262 setUI((TableUI
) UIManager
.getUI(this));
3268 * Get the class (datatype) of the column. The cells are rendered and edited
3269 * differently, depending from they data type.
3271 * @param column the column (not the model index).
3273 * @return the class, defining data type of that column (String.class for
3274 * String, Boolean.class for boolean and so on).
3276 public Class
getColumnClass(int column
)
3278 return getModel().getColumnClass(convertColumnIndexToModel(column
));
3282 * Get the name of the column. If the column has the column identifier set,
3283 * the return value is the result of the .toString() method call on that
3284 * identifier. If the identifier is not explicitly set, the returned value
3286 * {@link javax.swing.table.AbstractTableModel#getColumnName(int)}.
3288 * @param column the column
3290 * @return the name of that column.
3292 public String
getColumnName(int column
)
3294 int modelColumn
= columnModel
.getColumn(column
).getModelIndex();
3295 return dataModel
.getColumnName(modelColumn
);
3299 * Get the column, currently being edited
3301 * @return the column, currently being edited.
3303 public int getEditingColumn()
3305 return editingColumn
;
3309 * Set the column, currently being edited
3311 * @param column the column, currently being edited.
3313 public void setEditingColumn(int column
)
3315 editingColumn
= column
;
3319 * Get the row currently being edited.
3321 * @return the row, currently being edited.
3323 public int getEditingRow()
3329 * Set the row currently being edited.
3331 * @param row the row, that will be edited
3333 public void setEditingRow(int row
)
3339 * Get the editor component that is currently editing one of the cells
3341 * @return the editor component or null, if none of the cells is being
3344 public Component
getEditorComponent()
3350 * Check if one of the table cells is currently being edited.
3352 * @return true if there is a cell being edited.
3354 public boolean isEditing()
3356 return editorComp
!= null;
3360 * Set the default editor for the given column class (column data type).
3361 * By default, String is handled by text field and Boolean is handled by
3364 * @param columnClass the column data type
3365 * @param editor the editor that will edit this data type
3367 * @see TableModel#getColumnClass(int)
3369 public void setDefaultEditor(Class columnClass
, TableCellEditor editor
)
3372 defaultEditorsByColumnClass
.put(columnClass
, editor
);
3374 defaultEditorsByColumnClass
.remove(columnClass
);
3377 public void addColumnSelectionInterval(int index0
, int index1
)
3379 if ((index0
< 0 || index0
> (getColumnCount()-1)
3380 || index1
< 0 || index1
> (getColumnCount()-1)))
3381 throw new IllegalArgumentException("Column index out of range.");
3383 getColumnModel().getSelectionModel().addSelectionInterval(index0
, index1
);
3386 public void addRowSelectionInterval(int index0
, int index1
)
3388 if ((index0
< 0 || index0
> (getRowCount()-1)
3389 || index1
< 0 || index1
> (getRowCount()-1)))
3390 throw new IllegalArgumentException("Row index out of range.");
3392 getSelectionModel().addSelectionInterval(index0
, index1
);
3395 public void setColumnSelectionInterval(int index0
, int index1
)
3397 if ((index0
< 0 || index0
> (getColumnCount()-1)
3398 || index1
< 0 || index1
> (getColumnCount()-1)))
3399 throw new IllegalArgumentException("Column index out of range.");
3401 getColumnModel().getSelectionModel().setSelectionInterval(index0
, index1
);
3404 public void setRowSelectionInterval(int index0
, int index1
)
3406 if ((index0
< 0 || index0
> (getRowCount()-1)
3407 || index1
< 0 || index1
> (getRowCount()-1)))
3408 throw new IllegalArgumentException("Row index out of range.");
3410 getSelectionModel().setSelectionInterval(index0
, index1
);
3413 public void removeColumnSelectionInterval(int index0
, int index1
)
3415 if ((index0
< 0 || index0
> (getColumnCount()-1)
3416 || index1
< 0 || index1
> (getColumnCount()-1)))
3417 throw new IllegalArgumentException("Column index out of range.");
3419 getColumnModel().getSelectionModel().removeSelectionInterval(index0
, index1
);
3422 public void removeRowSelectionInterval(int index0
, int index1
)
3424 if ((index0
< 0 || index0
> (getRowCount()-1)
3425 || index1
< 0 || index1
> (getRowCount()-1)))
3426 throw new IllegalArgumentException("Row index out of range.");
3428 getSelectionModel().removeSelectionInterval(index0
, index1
);
3432 * Checks if the given column is selected.
3434 * @param column the column
3436 * @return true if the column is selected (as reported by the selection
3437 * model, associated with the column model), false otherwise.
3439 public boolean isColumnSelected(int column
)
3441 return getColumnModel().getSelectionModel().isSelectedIndex(column
);
3445 * Checks if the given row is selected.
3447 * @param row the row
3449 * @return true if the row is selected (as reported by the selection model),
3452 public boolean isRowSelected(int row
)
3454 return getSelectionModel().isSelectedIndex(row
);
3458 * Checks if the given cell is selected. The cell is selected if both
3459 * the cell row and the cell column are selected.
3461 * @param row the cell row
3462 * @param column the cell column
3464 * @return true if the cell is selected, false otherwise
3466 public boolean isCellSelected(int row
, int column
)
3468 return isRowSelected(row
) && isColumnSelected(column
);
3474 public void selectAll()
3476 // rowLead and colLead store the current lead selection indices
3477 int rowLead
= selectionModel
.getLeadSelectionIndex();
3478 int colLead
= getColumnModel().getSelectionModel().getLeadSelectionIndex();
3479 // the following calls to setSelectionInterval change the lead selection
3481 setColumnSelectionInterval(0, getColumnCount() - 1);
3482 setRowSelectionInterval(0, getRowCount() - 1);
3483 // the following addSelectionInterval calls restore the lead selection
3484 // indices to their previous values
3485 addColumnSelectionInterval(colLead
,colLead
);
3486 addRowSelectionInterval(rowLead
, rowLead
);
3490 * Get the cell value at the given position.
3492 * @param row the row to get the value
3493 * @param column the actual column number (not the model index)
3496 * @return the cell value, as returned by model.
3498 public Object
getValueAt(int row
, int column
)
3500 return dataModel
.getValueAt(row
, convertColumnIndexToModel(column
));
3504 * Set value for the cell at the given position. If the cell is not
3505 * editable, this method returns without action. The modified cell is
3508 * @param value the value to set
3509 * @param row the row of the cell being modified
3510 * @param column the column of the cell being modified
3512 public void setValueAt(Object value
, int row
, int column
)
3514 if (!isCellEditable(row
, column
))
3516 dataModel
.setValueAt(value
, row
, convertColumnIndexToModel(column
));
3518 repaint(getCellRect(row
, column
, true));
3522 * Get table column with the given identified.
3524 * @param identifier the column identifier
3526 * @return the table column with this identifier
3528 * @throws IllegalArgumentException if <code>identifier</code> is
3529 * <code>null</code> or there is no column with that identifier.
3531 * @see TableColumn#setIdentifier(Object)
3533 public TableColumn
getColumn(Object identifier
)
3535 return columnModel
.getColumn(columnModel
.getColumnIndex(identifier
));
3539 * Returns <code>true</code> if the specified cell is editable, and
3540 * <code>false</code> otherwise.
3542 * @param row the row index.
3543 * @param column the column index.
3545 * @return true if the cell is editable, false otherwise.
3547 public boolean isCellEditable(int row
, int column
)
3549 return dataModel
.isCellEditable(row
, convertColumnIndexToModel(column
));
3553 * Clears any existing columns from the <code>JTable</code>'s
3554 * {@link TableColumnModel} and creates new columns to match the values in
3555 * the data ({@link TableModel}) used by the table.
3557 * @see #setAutoCreateColumnsFromModel(boolean)
3559 public void createDefaultColumnsFromModel()
3561 assert columnModel
!= null : "The columnModel must not be null.";
3563 // remove existing columns
3564 int columnIndex
= columnModel
.getColumnCount() - 1;
3565 while (columnIndex
>= 0)
3567 columnModel
.removeColumn(columnModel
.getColumn(columnIndex
));
3571 // add new columns to match the TableModel
3572 int columnCount
= dataModel
.getColumnCount();
3573 for (int c
= 0; c
< columnCount
; c
++)
3575 TableColumn column
= new TableColumn(c
);
3576 column
.setIdentifier(dataModel
.getColumnName(c
));
3577 column
.setHeaderValue(dataModel
.getColumnName(c
));
3578 columnModel
.addColumn(column
);
3579 column
.addPropertyChangeListener(tableColumnPropertyChangeHandler
);
3583 public void changeSelection (int rowIndex
, int columnIndex
, boolean toggle
, boolean extend
)
3585 if (toggle
&& extend
)
3587 // Leave the selection state as is, but move the anchor
3588 // index to the specified location
3589 selectionModel
.setAnchorSelectionIndex(rowIndex
);
3590 getColumnModel().getSelectionModel().setAnchorSelectionIndex(columnIndex
);
3594 // Toggle the state of the specified cell
3595 if (isCellSelected(rowIndex
,columnIndex
))
3597 selectionModel
.removeSelectionInterval(rowIndex
,rowIndex
);
3598 getColumnModel().getSelectionModel().removeSelectionInterval(columnIndex
,columnIndex
);
3602 selectionModel
.addSelectionInterval(rowIndex
,rowIndex
);
3603 getColumnModel().getSelectionModel().addSelectionInterval(columnIndex
,columnIndex
);
3608 // Extend the previous selection from the anchor to the
3609 // specified cell, clearing all other selections
3610 selectionModel
.setLeadSelectionIndex(rowIndex
);
3611 getColumnModel().getSelectionModel().setLeadSelectionIndex(columnIndex
);
3615 // Clear the previous selection and ensure the new cell
3617 selectionModel
.clearSelection();
3618 selectionModel
.setSelectionInterval(rowIndex
,rowIndex
);
3619 getColumnModel().getSelectionModel().clearSelection();
3620 getColumnModel().getSelectionModel().setSelectionInterval(columnIndex
, columnIndex
);
3627 * Programmatically starts editing the specified cell.
3629 * @param row the row of the cell to edit.
3630 * @param column the column of the cell to edit.
3632 public boolean editCellAt (int row
, int column
)
3634 // Complete the previous editing session, if still active.
3636 editingStopped(new ChangeEvent("editingStopped"));
3639 editingColumn
= column
;
3641 setCellEditor(getCellEditor(row
, column
));
3642 editorComp
= prepareEditor(cellEditor
, row
, column
);
3644 // Remove the previous editor components, if present. Only one
3645 // editor component at time is allowed in the table.
3648 moveToCellBeingEdited(editorComp
);
3649 scrollRectToVisible(editorComp
.getBounds());
3650 editorComp
.requestFocusInWindow();
3655 * Move the given component under the cell being edited.
3656 * The table must be in the editing mode.
3658 * @param component the component to move.
3660 private void moveToCellBeingEdited(Component component
)
3662 Rectangle r
= getCellRect(editingRow
, editingColumn
, true);
3663 // Place the text field so that it would not touch the table
3666 // TODO Figure out while 5 and which constant should here be.
3673 // Clone rectangle as getCellRect returns the cached value.
3674 component
.setBounds(new Rectangle(r
));
3678 * Programmatically starts editing the specified cell.
3680 * @param row the row of the cell to edit.
3681 * @param column the column of the cell to edit.
3683 public boolean editCellAt (int row
, int column
, EventObject e
)
3685 return editCellAt(row
, column
);
3689 * Discards the editor object.
3691 public void removeEditor()
3693 editingStopped(new ChangeEvent(this));
3697 * Prepares the editor by querying for the value and selection state of the
3698 * cell at (row, column).
3700 * @param editor the TableCellEditor to set up
3701 * @param row the row of the cell to edit
3702 * @param column the column of the cell to edit
3703 * @return the Component being edited
3705 public Component
prepareEditor (TableCellEditor editor
, int row
, int column
)
3707 return editor
.getTableCellEditorComponent
3708 (this, getValueAt(row
, column
), isCellSelected(row
, column
), row
, column
);
3712 * This revalidates the <code>JTable</code> and queues a repaint.
3714 protected void resizeAndRepaint()
3721 * Sets whether cell editors of this table should receive keyboard focus
3722 * when the editor is activated by a keystroke. The default setting is
3723 * <code>false</code> which means that the table should keep the keyboard
3724 * focus until the cell is selected by a mouse click.
3726 * @param value the value to set
3730 public void setSurrendersFocusOnKeystroke(boolean value
)
3732 // TODO: Implement functionality of this property (in UI impl).
3733 surrendersFocusOnKeystroke
= value
;
3737 * Returns whether cell editors of this table should receive keyboard focus
3738 * when the editor is activated by a keystroke. The default setting is
3739 * <code>false</code> which means that the table should keep the keyboard
3740 * focus until the cell is selected by a mouse click.
3742 * @return whether cell editors of this table should receive keyboard focus
3743 * when the editor is activated by a keystroke
3747 public boolean getSurrendersFocusOnKeystroke()
3749 // TODO: Implement functionality of this property (in UI impl).
3750 return surrendersFocusOnKeystroke
;