diff options
Diffstat (limited to 'libjava/classpath/javax/swing/JTable.java')
-rw-r--r-- | libjava/classpath/javax/swing/JTable.java | 1012 |
1 files changed, 957 insertions, 55 deletions
diff --git a/libjava/classpath/javax/swing/JTable.java b/libjava/classpath/javax/swing/JTable.java index 21680d567e2..69a865df9c0 100644 --- a/libjava/classpath/javax/swing/JTable.java +++ b/libjava/classpath/javax/swing/JTable.java @@ -40,22 +40,34 @@ package javax.swing; import java.awt.Color; import java.awt.Component; +import java.awt.Cursor; import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; +import java.awt.event.FocusListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.text.DateFormat; import java.text.NumberFormat; import java.util.Date; import java.util.EventObject; import java.util.Hashtable; +import java.util.Locale; import java.util.Vector; import javax.accessibility.Accessible; +import javax.accessibility.AccessibleComponent; import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleExtendedTable; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleSelection; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleTable; +import javax.accessibility.AccessibleTableModelChange; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; @@ -76,10 +88,874 @@ import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; import javax.swing.text.Caret; -public class JTable extends JComponent +public class JTable + extends JComponent implements TableModelListener, Scrollable, TableColumnModelListener, ListSelectionListener, CellEditorListener, Accessible { + /** + * Provides accessibility support for <code>JTable</code>. + * + * @author Roman Kennke (kennke@aicas.com) + */ + protected class AccessibleJTable + extends AccessibleJComponent + implements AccessibleSelection, ListSelectionListener, TableModelListener, + TableColumnModelListener, CellEditorListener, PropertyChangeListener, + AccessibleExtendedTable + { + + /** + * Provides accessibility support for table cells. + * + * @author Roman Kennke (kennke@aicas.com) + */ + protected class AccessibleJTableCell + extends AccessibleContext + implements Accessible, AccessibleComponent + { + + /** + * The table of this cell. + */ + private JTable table; + + /** + * The row index of this cell. + */ + private int row; + + /** + * The column index of this cell. + */ + private int column; + + /** + * The index of this cell inside the AccessibleJTable parent. + */ + private int index; + + /** + * Creates a new <code>AccessibleJTableCell</code>. + * + * @param t the table + * @param r the row + * @param c the column + * @param i the index of this cell inside the accessible table parent + */ + public AccessibleJTableCell(JTable t, int r, int c, int i) + { + table = t; + row = r; + column = c; + index = i; + } + + /** + * Returns the accessible row for the table cell. + * + * @return the accessible row for the table cell + */ + public AccessibleRole getAccessibleRole() + { + // TODO: What is the role of the table cell? + return AccessibleRole.UNKNOWN; + } + + /** + * Returns the accessible state set of this accessible table cell. + * + * @return the accessible state set of this accessible table cell + */ + public AccessibleStateSet getAccessibleStateSet() + { + // TODO: What state shoiuld be returned here? + return new AccessibleStateSet(); + } + + /** + * Returns the index of this cell in the parent object. + * + * @return the index of this cell in the parent object + */ + public int getAccessibleIndexInParent() + { + return index; + } + + /** + * Returns the number of children of this object. Table cells cannot have + * children, so we return <code>0</code> here. + * + * @return <code>0</code> + */ + public int getAccessibleChildrenCount() + { + return 0; + } + + /** + * Returns the accessible child at index <code>i</code>. Table cells + * don't have children, so we return <code>null</code> here. + * + * @return <code>null</code> + */ + public Accessible getAccessibleChild(int i) + { + return null; + } + + /** + * Returns the locale setting for this accessible table cell. + * + * @return the locale setting for this accessible table cell + */ + public Locale getLocale() + { + // TODO: For now, we return english here. This must be fixed as soon + // as we have a localized Swing. + return Locale.ENGLISH; + } + + /** + * Returns the accessible context of this table cell. Since accessible + * table cells are their own accessible context, we return + * <code>this</code>. + * + * @return the accessible context of this table cell + */ + public AccessibleContext getAccessibleContext() + { + return this; + } + + /** + * Returns the background color of this cell. + * + * @return the background color of this cell + */ + public Color getBackground() + { + return table.getBackground(); + } + + /** + * Sets the background of the cell. Since table cells cannot have + * individual background colors, this method does nothing. Set the + * background directly on the table instead. + * + * @param color not used + */ + public void setBackground(Color color) + { + // This method does nothing. See API comments. + } + + /** + * Returns the foreground color of the table cell. + * + * @return the foreground color of the table cell + */ + public Color getForeground() + { + return table.getForeground(); + } + + /** + * Sets the foreground of the cell. Since table cells cannot have + * individual foreground colors, this method does nothing. Set the + * foreground directly on the table instead. + * + * @param color not used + */ + public void setForeground(Color color) + { + // This method does nothing. See API comments. + } + + /** + * Returns the cursor for this table cell. + * + * @return the cursor for this table cell + */ + public Cursor getCursor() + { + return table.getCursor(); + } + + /** + * Sets the cursor of the cell. Since table cells cannot have + * individual cursors, this method does nothing. Set the + * cursor directly on the table instead. + * + * @param cursor not used + */ + public void setCursor(Cursor cursor) + { + // This method does nothing. See API comments. + } + + /** + * Returns the font of the table cell. + * + * @return the font of the table cell + */ + public Font getFont() + { + return table.getFont(); + } + + /** + * Sets the font of the cell. Since table cells cannot have + * individual fonts, this method does nothing. Set the + * font directly on the table instead. + * + * @param font not used + */ + public void setFont(Font font) + { + // This method does nothing. See API comments. + } + + /** + * Returns the font metrics for a specified font. + * + * @param font the font for which we return the metrics + * + * @return the font metrics for a specified font + */ + public FontMetrics getFontMetrics(Font font) + { + return table.getFontMetrics(font); + } + + /** + * Returns <code>true</code> if this table cell is enabled, + * <code>false</code> otherwise. + * + * @return <code>true</code> if this table cell is enabled, + * <code>false</code> otherwise + */ + public boolean isEnabled() + { + return table.isEnabled(); + } + + /** + * Table cells cannot be disabled or enabled individually, so this method + * does nothing. Set the enabled flag on the table itself. + * + * @param b not used here + */ + public void setEnabled(boolean b) + { + // This method does nothing. See API comments. + } + + /** + * Returns <code>true</code> if this cell is visible, <code>false</code> + * otherwise. + * + * @return <code>true</code> if this cell is visible, <code>false</code> + * otherwise + */ + public boolean isVisible() + { + return table.isVisible(); + } + + /** + * The visibility cannot be set on individual table cells, so this method + * does nothing. Set the visibility on the table itself. + * + * @param b not used + */ + public void setVisible(boolean b) + { + // This method does nothing. See API comments. + } + + /** + * Returns <code>true</code> if this table cell is currently showing on + * screen. + * + * @return <code>true</code> if this table cell is currently showing on + * screen + */ + public boolean isShowing() + { + return table.isShowing(); + } + + /** + * Returns <code>true</code> if this table cell contains the location + * at <code>point</code>, <code>false</code> otherwise. + * <code>point</code> is interpreted as relative to the coordinate system + * of the table cell. + * + * @return <code>true</code> if this table cell contains the location + * at <code>point</code>, <code>false</code> otherwise + */ + public boolean contains(Point point) + { + Rectangle cellRect = table.getCellRect(row, column, true); + cellRect.x = 0; + cellRect.y = 0; + return cellRect.contains(point); + } + + /** + * Returns the screen location of the table cell. + * + * @return the screen location of the table cell + */ + public Point getLocationOnScreen() + { + Point tableLoc = table.getLocationOnScreen(); + Rectangle cellRect = table.getCellRect(row, column, true); + tableLoc.x += cellRect.x; + tableLoc.y += cellRect.y; + return tableLoc; + } + + /** + * Returns the location of this cell relative to the table's bounds. + * + * @return the location of this cell relative to the table's bounds + */ + public Point getLocation() + { + Rectangle cellRect = table.getCellRect(row, column, true); + return new Point(cellRect.x, cellRect.y); + } + + /** + * The location of the table cells cannot be manipulated directly, so + * this method does nothing. + * + * @param point not used + */ + public void setLocation(Point point) + { + // This method does nothing. See API comments. + } + + /** + * Returns the bounds of the cell relative to its table. + * + * @return the bounds of the cell relative to its table + */ + public Rectangle getBounds() + { + return table.getCellRect(row, column, true); + } + + /** + * The bounds of the table cells cannot be manipulated directly, so + * this method does nothing. + * + * @param rectangle not used + */ + public void setBounds(Rectangle rectangle) + { + // This method does nothing. See API comments. + } + + /** + * Returns the size of the table cell. + * + * @return the size of the table cell + */ + public Dimension getSize() + { + Rectangle cellRect = table.getCellRect(row, column, true); + return new Dimension(cellRect.width, cellRect.height); + } + + /** + * The size cannot be set on table cells directly, so this method does + * nothing. + * + * @param dimension not used + */ + public void setSize(Dimension dimension) + { + // This method does nothing. See API comments. + } + + /** + * Table cells have no children, so we return <code>null</code> here. + * + * @return <code>null</code> + */ + public Accessible getAccessibleAt(Point point) + { + return null; + } + + /** + * Returns <code>true</code> if this table cell is focus traversable, + * <code>false</code> otherwise. + * + * @return <code>true</code> if this table cell is focus traversable, + * <code>false</code> otherwise + */ + public boolean isFocusTraversable() + { + return table.isFocusable(); + } + + /** + * Requests that this table cell gets the keyboard focus. + */ + public void requestFocus() + { + // We first set the selection models' lead selection to this cell. + table.getColumnModel().getSelectionModel() + .setLeadSelectionIndex(column); + table.getSelectionModel().setLeadSelectionIndex(row); + // Now we request that the table receives focus. + table.requestFocus(); + } + + /** + * Adds a focus listener to this cell. The focus listener is really + * added to the table, so there is no way to find out when an individual + * cell changes the focus. + * + * @param listener the focus listener to add + */ + public void addFocusListener(FocusListener listener) + { + table.addFocusListener(listener); + } + + /** + * Removes a focus listener from the cell. The focus listener is really + * removed from the table. + * + * @param listener the listener to remove + */ + public void removeFocusListener(FocusListener listener) + { + table.removeFocusListener(listener); + } + + } + + protected class AccessibleJTableModelChange + implements AccessibleTableModelChange + { + protected int type; + protected int firstRow; + protected int lastRow; + protected int firstColumn; + protected int lastColumn; + + protected AccessibleJTableModelChange(int type, int firstRow, + int lastRow, int firstColumn, + int lastColumn) + { + this.type = type; + this.firstRow = firstRow; + this.lastRow = lastRow; + this.firstColumn = firstColumn; + this.lastColumn = lastColumn; + } + + public int getType() + { + return type; + } + + public int getFirstRow() + { + return firstRow; + } + + public int getLastRow() + { + return lastRow; + } + + public int getFirstColumn() + { + return firstColumn; + } + + public int getLastColumn() + { + return lastColumn; + } + } + + /** + * Creates a new <code>AccessibleJTable</code>. + * + * @since JDK1.5 + */ + protected AccessibleJTable() + { + getModel().addTableModelListener(this); + getSelectionModel().addListSelectionListener(this); + getColumnModel().addColumnModelListener(this); + getCellEditor().addCellEditorListener(this); + } + + /** + * Returns the number of selected items in this table. + */ + public int getAccessibleSelectionCount() + { + return getSelectedColumnCount(); + } + + public Accessible getAccessibleSelection(int i) + { + // TODO Auto-generated method stub + return null; + } + + public boolean isAccessibleChildSelected(int i) + { + // TODO Auto-generated method stub + return false; + } + + public void addAccessibleSelection(int i) + { + // TODO Auto-generated method stub + + } + + public void removeAccessibleSelection(int i) + { + // TODO Auto-generated method stub + + } + + public void clearAccessibleSelection() + { + // TODO Auto-generated method stub + + } + + public void selectAllAccessibleSelection() + { + // TODO Auto-generated method stub + + } + + public void valueChanged(ListSelectionEvent event) + { + // TODO Auto-generated method stub + + } + + /** + * Receives notification when the table model changes. Depending on the + * type of change, this method calls {@link #tableRowsInserted} or + * {@link #tableRowsDeleted}. + * + * @param event the table model event + */ + public void tableChanged(TableModelEvent event) + { + switch (event.getType()) + { + case TableModelEvent.INSERT: + tableRowsInserted(event); + break; + case TableModelEvent.DELETE: + tableRowsDeleted(event); + break; + } + } + + /** + * Receives notification when one or more rows have been inserted into the + * table. + * + * @param event the table model event + */ + public void tableRowsInserted(TableModelEvent event) + { + // TODO: What to do here, if anything? This might be a hook method for + // subclasses... + } + + /** + * Receives notification when one or more rows have been deleted from the + * table. + * + * @param event the table model event + */ + public void tableRowsDeleted(TableModelEvent event) + { + // TODO: What to do here, if anything? This might be a hook method for + // subclasses... + } + + public void columnAdded(TableColumnModelEvent event) + { + // TODO Auto-generated method stub + + } + + public void columnMarginChanged(ChangeEvent event) + { + // TODO Auto-generated method stub + + } + + public void columnMoved(TableColumnModelEvent event) + { + // TODO Auto-generated method stub + + } + + public void columnRemoved(TableColumnModelEvent event) + { + // TODO Auto-generated method stub + + } + + public void columnSelectionChanged(ListSelectionEvent event) + { + // TODO Auto-generated method stub + + } + + public void editingCanceled(ChangeEvent event) + { + // TODO Auto-generated method stub + + } + + public void editingStopped(ChangeEvent event) + { + // TODO Auto-generated method stub + + } + + /** + * Receives notification when any of the JTable's properties changes. This + * is used to replace the listeners on the table's model, selection model, + * column model and cell editor. + * + * @param e the property change event + */ + public void propertyChange(PropertyChangeEvent e) + { + String propName = e.getPropertyName(); + if (propName.equals("tableModel")) + { + TableModel oldModel = (TableModel) e.getOldValue(); + oldModel.removeTableModelListener(this); + TableModel newModel = (TableModel) e.getNewValue(); + newModel.addTableModelListener(this); + } + else if (propName.equals("columnModel")) + { + TableColumnModel oldModel = (TableColumnModel) e.getOldValue(); + oldModel.removeColumnModelListener(this); + TableColumnModel newModel = (TableColumnModel) e.getNewValue(); + newModel.addColumnModelListener(this); + } + else if (propName.equals("selectionModel")) + { + ListSelectionModel oldModel = (ListSelectionModel) e.getOldValue(); + oldModel.removeListSelectionListener(this); + ListSelectionModel newModel = (ListSelectionModel) e.getNewValue(); + newModel.addListSelectionListener(this); + } + else if (propName.equals("cellEditor")) + { + CellEditor oldEd = (CellEditor) e.getOldValue(); + oldEd.removeCellEditorListener(this); + CellEditor newEd = (CellEditor) e.getNewValue(); + newEd.addCellEditorListener(this); + } + } + + public int getAccessibleRow(int index) + { + // TODO Auto-generated method stub + return 0; + } + + public int getAccessibleColumn(int index) + { + // TODO Auto-generated method stub + return 0; + } + + public int getAccessibleIndex(int r, int c) + { + // TODO Auto-generated method stub + return 0; + } + + public Accessible getAccessibleCaption() + { + // TODO Auto-generated method stub + return null; + } + + public void setAccessibleCaption(Accessible caption) + { + // TODO Auto-generated method stub + + } + + public Accessible getAccessibleSummary() + { + // TODO Auto-generated method stub + return null; + } + + public void setAccessibleSummary(Accessible summary) + { + // TODO Auto-generated method stub + + } + + public int getAccessibleRowCount() + { + // TODO Auto-generated method stub + return 0; + } + + public int getAccessibleColumnCount() + { + // TODO Auto-generated method stub + return 0; + } + + public Accessible getAccessibleAt(int r, int c) + { + // TODO Auto-generated method stub + return null; + } + + public int getAccessibleRowExtentAt(int r, int c) + { + // TODO Auto-generated method stub + return 0; + } + + public int getAccessibleColumnExtentAt(int r, int c) + { + // TODO Auto-generated method stub + return 0; + } + + public AccessibleTable getAccessibleRowHeader() + { + // TODO Auto-generated method stub + return null; + } + + public void setAccessibleRowHeader(AccessibleTable header) + { + // TODO Auto-generated method stub + + } + + public AccessibleTable getAccessibleColumnHeader() + { + // TODO Auto-generated method stub + return null; + } + + public void setAccessibleColumnHeader(AccessibleTable header) + { + // TODO Auto-generated method stub + + } + + public Accessible getAccessibleRowDescription(int r) + { + // TODO Auto-generated method stub + return null; + } + + public void setAccessibleRowDescription(int r, Accessible description) + { + // TODO Auto-generated method stub + + } + + public Accessible getAccessibleColumnDescription(int c) + { + // TODO Auto-generated method stub + return null; + } + + public void setAccessibleColumnDescription(int c, Accessible description) + { + // TODO Auto-generated method stub + + } + + public boolean isAccessibleSelected(int r, int c) + { + // TODO Auto-generated method stub + return false; + } + + public boolean isAccessibleRowSelected(int r) + { + // TODO Auto-generated method stub + return false; + } + + public boolean isAccessibleColumnSelected(int c) + { + // TODO Auto-generated method stub + return false; + } + + public int[] getSelectedAccessibleRows() + { + // TODO Auto-generated method stub + return null; + } + + public int[] getSelectedAccessibleColumns() + { + // TODO Auto-generated method stub + return null; + } + + } + /** + * Handles property changes from the <code>TableColumn</code>s of this + * <code>JTable</code>. + * + * More specifically, this triggers a {@link #revalidate()} call if the + * preferredWidth of one of the observed columns changes. + */ + class TableColumnPropertyChangeHandler implements PropertyChangeListener + { + /** + * Receives notification that a property of the observed TableColumns + * has changed. + * + * @param ev the property change event + */ + public void propertyChange(PropertyChangeEvent ev) + { + if (ev.getPropertyName().equals("preferredWidth")) + { + JTableHeader header = getTableHeader(); + TableColumn col = (TableColumn) ev.getSource(); + header.setResizingColumn(col); + doLayout(); + header.setResizingColumn(null); + } + } + } /** * A cell renderer for boolean values. @@ -364,7 +1240,7 @@ public class JTable extends JComponent * property when the {@link #dataModel} property is changed. * * @see #setModel(TableModel) - * @see #createColumnsFromModel() + * @see #createDefaultColumnsFromModel() * @see #setColumnModel(TableColumnModel) * @see #setAutoCreateColumnsFromModel(boolean) * @see #getAutoCreateColumnsFromModel() @@ -480,11 +1356,6 @@ public class JTable extends JComponent protected ListSelectionModel selectionModel; /** - * The accessibleContext property. - */ - protected AccessibleContext accessibleContext; - - /** * The current cell editor. */ protected TableCellEditor cellEditor; @@ -492,7 +1363,7 @@ public class JTable extends JComponent /** * Whether or not drag-and-drop is enabled on this table. * - * @see #setDragEnabled() + * @see #setDragEnabled(boolean) * @see #getDragEnabled() */ private boolean dragEnabled; @@ -584,6 +1455,12 @@ public class JTable extends JComponent Object oldCellValue; /** + * The property handler for this table's columns. + */ + TableColumnPropertyChangeHandler tableColumnPropertyChangeHandler = + new TableColumnPropertyChangeHandler(); + + /** * Creates a new <code>JTable</code> instance. */ public JTable () @@ -643,15 +1520,28 @@ public class JTable extends JComponent */ public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm) { - setModel(dm == null ? createDefaultDataModel() : dm); + boolean autoCreate = false; + if (cm != null) + setColumnModel(cm); + else + { + setColumnModel(createDefaultColumnModel()); + autoCreate = true; + } setSelectionModel(sm == null ? createDefaultSelectionModel() : sm); - - this.columnModel = cm; + setModel(dm == null ? createDefaultDataModel() : dm); + setAutoCreateColumnsFromModel(autoCreate); initializeLocalVars(); - // The next two lines are for compliance with the JDK which starts - // the JLists associated with a JTable with both lead selection - // indices at 0, rather than -1 as in regular JLists + // The following four lines properly set the lead selection indices. + // After this, the UI will handle the lead selection indices. + // FIXME: this should probably not be necessary, if the UI is installed + // before the TableModel is set then the UI will handle things on its + // own, but certain variables need to be set before the UI can be installed + // so we must get the correct order for all the method calls in this + // constructor. + selectionModel.setAnchorSelectionIndex(0); selectionModel.setLeadSelectionIndex(0); + columnModel.getSelectionModel().setAnchorSelectionIndex(0); columnModel.getSelectionModel().setLeadSelectionIndex(0); updateUI(); } @@ -659,12 +1549,8 @@ public class JTable extends JComponent protected void initializeLocalVars() { setTableHeader(createDefaultTableHeader()); - this.autoCreateColumnsFromModel = false; - if (columnModel == null) - { - this.autoCreateColumnsFromModel = true; - createColumnsFromModel(); - } + if (autoCreateColumnsFromModel) + createDefaultColumnsFromModel(); this.columnModel.addColumnModelListener(this); this.defaultRenderersByColumnClass = new Hashtable(); @@ -754,6 +1640,7 @@ public class JTable extends JComponent } columnModel.addColumn(column); + column.addPropertyChangeListener(tableColumnPropertyChangeHandler); } protected void createDefaultEditors() @@ -799,20 +1686,6 @@ public class JTable extends JComponent return new JTableHeader(columnModel); } - private void createColumnsFromModel() - { - if (dataModel == null) - return; - - TableColumnModel cm = createDefaultColumnModel(); - - for (int i = 0; i < dataModel.getColumnCount(); ++i) - { - cm.addColumn(new TableColumn(i)); - } - this.setColumnModel(cm); - } - // listener support public void columnAdded (TableColumnModelEvent event) @@ -890,8 +1763,19 @@ public class JTable extends JComponent if ((event.getFirstRow() ==TableModelEvent.HEADER_ROW) && autoCreateColumnsFromModel) - createColumnsFromModel(); + createDefaultColumnsFromModel(); + // If the structure changes, we need to revalidate, since that might + // affect the size parameters of the JTable. Otherwise we only need + // to perform a repaint to update the view. + if (event.getType() == TableModelEvent.INSERT) + revalidate(); + else if (event.getType() == TableModelEvent.DELETE) + { + if (dataModel.getRowCount() == 0) + clearSelection(); + revalidate(); + } repaint(); } @@ -944,8 +1828,7 @@ public class JTable extends JComponent { int y0 = getLocation().y; int nrows = getRowCount(); - Dimension gap = getIntercellSpacing(); - int height = getRowHeight() + (gap == null ? 0 : gap.height); + int height = getRowHeight(); int y = point.y; for (int i = 0; i < nrows; ++i) @@ -990,10 +1873,7 @@ public class JTable extends JComponent int y = (height + y_gap) * row; for (int i = 0; i < column; ++i) - { - x += columnModel.getColumn(i).getWidth(); - x += x_gap; - } + x += columnModel.getColumn(i).getWidth(); if (includeSpacing) return new Rectangle(x, y, width, height); @@ -1015,7 +1895,7 @@ public class JTable extends JComponent * @return The current value of the selectedRow property */ public int getSelectedRow () - { + { return selectionModel.getMinSelectionIndex(); } @@ -1069,13 +1949,14 @@ public class JTable extends JComponent // scroll direction. if (orientation == SwingConstants.VERTICAL) - return rowHeight; + return direction * rowHeight; else { int sum = 0; for (int i = 0; i < getColumnCount(); ++i) sum += columnModel.getColumn(0).getWidth(); - return getColumnCount() == 0 ? 10 : sum / getColumnCount(); + int inc = getColumnCount() == 0 ? 10 : sum / getColumnCount(); + return direction * inc; } } @@ -1656,24 +2537,29 @@ public class JTable extends JComponent // Don't do anything if setting the current model again. if (dataModel == m) return; - + + TableModel oldModel = dataModel; + // Remove table as TableModelListener from old model. if (dataModel != null) dataModel.removeTableModelListener(this); if (m != null) { - // Set property. + // Set property. dataModel = m; - // Add table as TableModelListener to new model. - dataModel.addTableModelListener(this); + // Add table as TableModelListener to new model. + dataModel.addTableModelListener(this); - // Automatically create columns. - if (autoCreateColumnsFromModel) - createColumnsFromModel(); + // Automatically create columns. + if (autoCreateColumnsFromModel) + createDefaultColumnsFromModel(); } - + + // This property is bound, so we fire a property change event. + firePropertyChange("model", oldModel, dataModel); + // Repaint table. revalidate(); repaint(); @@ -1959,7 +2845,8 @@ public class JTable extends JComponent int average = spill / cols.length; for (int i = 0; i < cols.length; i++) { - cols[i].setWidth(cols[i].getWidth() + average); + if (cols[i] != null) + cols[i].setWidth(cols[i].getWidth() + average); } } @@ -2023,6 +2910,8 @@ public class JTable extends JComponent case AUTO_RESIZE_OFF: default: + int prefWidth = resizingColumn.getPreferredWidth(); + resizingColumn.setWidth(prefWidth); } } else @@ -2258,6 +3147,8 @@ public class JTable extends JComponent */ public void createDefaultColumnsFromModel() { + assert columnModel != null : "The columnModel must not be null."; + // remove existing columns int columnIndex = columnModel.getColumnCount() - 1; while (columnIndex >= 0) @@ -2272,7 +3163,9 @@ public class JTable extends JComponent { TableColumn column = new TableColumn(c); column.setIdentifier(dataModel.getColumnName(c)); + column.setHeaderValue(dataModel.getColumnName(c)); columnModel.addColumn(column); + column.addPropertyChangeListener(tableColumnPropertyChangeHandler); } } @@ -2372,4 +3265,13 @@ public class JTable extends JComponent return editor.getTableCellEditorComponent (this, getValueAt(row, column), isCellSelected(row, column), row, column); } + + /** + * This revalidates the <code>JTable</code> and queues a repaint. + */ + protected void resizeAndRepaint() + { + revalidate(); + repaint(); + } } |