| /* DefaultTableModel.java -- |
| Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package javax.swing.table; |
| |
| import java.io.Serializable; |
| import java.util.Vector; |
| |
| import javax.swing.event.TableModelEvent; |
| |
| /** |
| * A two dimensional data structure used to store <code>Object</code> |
| * instances, usually for display in a <code>JTable</code> component. |
| * |
| * @author Andrew Selkirk |
| */ |
| public class DefaultTableModel extends AbstractTableModel |
| implements Serializable |
| { |
| static final long serialVersionUID = 6680042567037222321L; |
| |
| /** |
| * Storage for the rows in the table (each row is itself |
| * a <code>Vector</code>). |
| */ |
| protected Vector dataVector; |
| |
| /** |
| * Storage for the column identifiers. |
| */ |
| protected Vector columnIdentifiers; |
| |
| /** |
| * Creates an empty table with zero rows and zero columns. |
| */ |
| public DefaultTableModel() |
| { |
| this(0, 0); |
| } |
| |
| /** |
| * Creates a new table with the specified number of rows and columns. |
| * All cells in the table are initially empty (set to <code>null</code>). |
| * |
| * @param numRows the number of rows. |
| * @param numColumns the number of columns. |
| */ |
| public DefaultTableModel(int numRows, int numColumns) |
| { |
| Vector defaultNames = new Vector(numColumns); |
| Vector data = new Vector(numRows); |
| for (int i = 0; i < numColumns; i++) |
| { |
| defaultNames.add(super.getColumnName(i)); |
| } |
| for (int r = 0; r < numRows; r++) |
| { |
| Vector tmp = new Vector(numColumns); |
| tmp.setSize(numColumns); |
| data.add(tmp); |
| } |
| setDataVector(data, defaultNames); |
| } |
| |
| /** |
| * Creates a new table with the specified column names and number of |
| * rows. The number of columns is determined by the number of column |
| * names supplied. |
| * |
| * @param columnNames the column names. |
| * @param numRows the number of rows. |
| */ |
| public DefaultTableModel(Vector columnNames, int numRows) |
| { |
| if (numRows < 0) |
| throw new IllegalArgumentException("numRows < 0"); |
| Vector data = new Vector(); |
| int numColumns = 0; |
| |
| if (columnNames != null) |
| numColumns = columnNames.size(); |
| |
| while (0 < numRows--) |
| { |
| Vector rowData = new Vector(); |
| rowData.setSize(numColumns); |
| data.add(rowData); |
| } |
| setDataVector(data, columnNames); |
| } |
| |
| /** |
| * Creates a new table with the specified column names and row count. |
| * |
| * @param columnNames the column names. |
| * @param numRows the number of rows. |
| */ |
| public DefaultTableModel(Object[] columnNames, int numRows) |
| { |
| this(convertToVector(columnNames), numRows); |
| } |
| |
| /** |
| * Creates a new table with the specified data values and column names. |
| * |
| * @param data the data values. |
| * @param columnNames the column names. |
| */ |
| public DefaultTableModel(Vector data, Vector columnNames) |
| { |
| setDataVector(data, columnNames); |
| } |
| |
| /** |
| * Creates a new table with the specified data values and column names. |
| * |
| * @param data the data values. |
| * @param columnNames the column names. |
| */ |
| public DefaultTableModel(Object[][] data, Object[] columnNames) |
| { |
| this(convertToVector(data), convertToVector(columnNames)); |
| } |
| |
| /** |
| * Returns the vector containing the row data for the table. |
| * |
| * @return The data vector. |
| */ |
| public Vector getDataVector() |
| { |
| return dataVector; |
| } |
| |
| /** |
| * Sets the data and column identifiers for the table. The data vector |
| * contains a <code>Vector</code> for each row in the table - if the |
| * number of objects in each row does not match the number of column |
| * names specified, the row data is truncated or expanded (by adding |
| * <code>null</code> values) as required. |
| * |
| * @param data the data for the table (a vector of row vectors). |
| * @param columnNames the column names. |
| * |
| * @throws NullPointerException if either argument is <code>null</code>. |
| */ |
| public void setDataVector(Vector data, Vector columnNames) |
| { |
| if (data == null) |
| dataVector = new Vector(); |
| else |
| dataVector = data; |
| setColumnIdentifiers(columnNames); |
| } |
| |
| /** |
| * Sets the data and column identifiers for the table. |
| * |
| * @param data the data for the table. |
| * @param columnNames the column names. |
| * |
| * @throws NullPointerException if either argument is <code>null</code>. |
| */ |
| public void setDataVector(Object[][] data, Object[] columnNames) |
| { |
| setDataVector(convertToVector(data), |
| convertToVector(columnNames)); |
| } |
| |
| /** |
| * Sends the specified <code>event</code> to all registered listeners. |
| * This method is equivalent to |
| * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}. |
| * |
| * @param event the event. |
| */ |
| public void newDataAvailable(TableModelEvent event) |
| { |
| fireTableChanged(event); |
| } |
| |
| /** |
| * Sends the specified <code>event</code> to all registered listeners. |
| * This method is equivalent to |
| * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}. |
| * |
| * @param event the event. |
| */ |
| public void newRowsAdded(TableModelEvent event) |
| { |
| fireTableChanged(event); |
| } |
| |
| /** |
| * Sends the specified <code>event</code> to all registered listeners. |
| * This method is equivalent to |
| * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}. |
| * |
| * @param event the event. |
| */ |
| public void rowsRemoved(TableModelEvent event) |
| { |
| fireTableChanged(event); |
| } |
| |
| /** |
| * Sets the column identifiers, updates the data rows (truncating |
| * or padding each row with <code>null</code> values) to match the |
| * number of columns, and sends a {@link TableModelEvent} to all |
| * registered listeners. |
| * |
| * @param columnIdentifiers the column identifiers. |
| */ |
| public void setColumnIdentifiers(Vector columnIdentifiers) |
| { |
| this.columnIdentifiers = columnIdentifiers; |
| setColumnCount(columnIdentifiers == null ? 0 : columnIdentifiers.size()); |
| } |
| |
| /** |
| * Sets the column identifiers, updates the data rows (truncating |
| * or padding each row with <code>null</code> values) to match the |
| * number of columns, and sends a {@link TableModelEvent} to all |
| * registered listeners. |
| * |
| * @param columnIdentifiers the column identifiers. |
| */ |
| public void setColumnIdentifiers(Object[] columnIdentifiers) |
| { |
| setColumnIdentifiers(convertToVector(columnIdentifiers)); |
| } |
| |
| /** |
| * This method is obsolete, use {@link #setRowCount(int)} instead. |
| * |
| * @param numRows the number of rows. |
| */ |
| public void setNumRows(int numRows) |
| { |
| setRowCount(numRows); |
| } |
| |
| /** |
| * Sets the number of rows in the table. If <code>rowCount</code> is less |
| * than the current number of rows in the table, rows are discarded. |
| * If <code>rowCount</code> is greater than the current number of rows in |
| * the table, new (empty) rows are added. |
| * |
| * @param rowCount the row count. |
| */ |
| public void setRowCount(int rowCount) |
| { |
| int existingRowCount = dataVector.size(); |
| if (rowCount < existingRowCount) |
| { |
| dataVector.setSize(rowCount); |
| fireTableRowsDeleted(rowCount, existingRowCount - 1); |
| } |
| else |
| { |
| int rowsToAdd = rowCount - existingRowCount; |
| addExtraRows(rowsToAdd, columnIdentifiers.size()); |
| fireTableRowsInserted(existingRowCount, rowCount - 1); |
| } |
| } |
| |
| /** |
| * Sets the number of columns in the table. Existing rows are truncated |
| * or padded with <code>null</code> values to match the new column count. |
| * A {@link TableModelEvent} is sent to all registered listeners. |
| * |
| * @param columnCount the column count. |
| */ |
| public void setColumnCount(int columnCount) |
| { |
| for (int i = 0; i < dataVector.size(); ++i) |
| { |
| ((Vector) dataVector.get(i)).setSize(columnCount); |
| } |
| if (columnIdentifiers != null) |
| columnIdentifiers.setSize(columnCount); |
| fireTableStructureChanged(); |
| } |
| |
| /** |
| * Adds a column with the specified name to the table. All cell values |
| * for the column are initially set to <code>null</code>. |
| * |
| * @param columnName the column name (<code>null</code> permitted). |
| */ |
| public void addColumn(Object columnName) |
| { |
| addColumn(columnName, (Object[]) null); |
| } |
| |
| /** |
| * Adds a column with the specified name and data values to the table. |
| * |
| * @param columnName the column name (<code>null</code> permitted). |
| * @param columnData the column data. |
| */ |
| public void addColumn(Object columnName, Vector columnData) |
| { |
| Object[] dataArray = null; |
| if (columnData != null) |
| { |
| int rowCount = dataVector.size(); |
| if (columnData.size() < rowCount) |
| columnData.setSize(rowCount); |
| dataArray = columnData.toArray(); |
| } |
| addColumn(columnName, dataArray); |
| } |
| |
| /** |
| * Adds a column with the specified name and data values to the table. |
| * |
| * @param columnName the column name (<code>null</code> permitted). |
| * @param columnData the column data. |
| */ |
| public void addColumn(Object columnName, Object[] columnData) |
| { |
| if (columnData != null) |
| { |
| // check columnData array for cases where the number of items |
| // doesn't match the number of rows in the existing table |
| if (columnData.length > dataVector.size()) |
| { |
| int rowsToAdd = columnData.length - dataVector.size(); |
| addExtraRows(rowsToAdd, columnIdentifiers.size()); |
| } |
| else if (columnData.length < dataVector.size()) |
| { |
| Object[] tmp = new Object[dataVector.size()]; |
| System.arraycopy(columnData, 0, tmp, 0, columnData.length); |
| columnData = tmp; |
| } |
| } |
| for (int i = 0; i < dataVector.size(); ++i) |
| { |
| ((Vector) dataVector.get(i)).add(columnData == null ? null : columnData[i]); |
| } |
| columnIdentifiers.add(columnName); |
| fireTableStructureChanged(); |
| } |
| |
| /** |
| * Adds a new row containing the specified data to the table and sends a |
| * {@link TableModelEvent} to all registered listeners. |
| * |
| * @param rowData the row data (<code>null</code> permitted). |
| */ |
| public void addRow(Vector rowData) |
| { |
| int rowIndex = dataVector.size(); |
| dataVector.add(rowData); |
| newRowsAdded(new TableModelEvent( |
| this, rowIndex, rowIndex, -1, TableModelEvent.INSERT) |
| ); |
| } |
| |
| /** |
| * Adds a new row containing the specified data to the table and sends a |
| * {@link TableModelEvent} to all registered listeners. |
| * |
| * @param rowData the row data (<code>null</code> permitted). |
| */ |
| public void addRow(Object[] rowData) |
| { |
| addRow(convertToVector(rowData)); |
| } |
| |
| /** |
| * Inserts a new row into the table. |
| * |
| * @param row the row index. |
| * @param rowData the row data. |
| */ |
| public void insertRow(int row, Vector rowData) |
| { |
| dataVector.add(row, rowData); |
| fireTableRowsInserted(row, row); |
| } |
| |
| /** |
| * Inserts a new row into the table. |
| * |
| * @param row the row index. |
| * @param rowData the row data. |
| */ |
| public void insertRow(int row, Object[] rowData) |
| { |
| insertRow(row, convertToVector(rowData)); |
| } |
| |
| /** |
| * Moves the rows from <code>startIndex</code> to <code>endIndex</code> |
| * (inclusive) to the specified row. |
| * |
| * @param startIndex the start row. |
| * @param endIndex the end row. |
| * @param toIndex the row to move to. |
| */ |
| public void moveRow(int startIndex, int endIndex, int toIndex) |
| { |
| Vector removed = new Vector(); |
| for (int i = endIndex; i >= startIndex; i--) |
| { |
| removed.add(this.dataVector.remove(i)); |
| } |
| for (int i = 0; i <= endIndex - startIndex; i++) |
| { |
| dataVector.insertElementAt(removed.get(i), toIndex); |
| } |
| int firstRow = Math.min(startIndex, toIndex); |
| int lastRow = Math.max(endIndex, toIndex + (endIndex - startIndex)); |
| fireTableRowsUpdated(firstRow, lastRow); |
| } |
| |
| /** |
| * Removes a row from the table and sends a {@link TableModelEvent} to |
| * all registered listeners. |
| * |
| * @param row the row index. |
| */ |
| public void removeRow(int row) |
| { |
| dataVector.remove(row); |
| fireTableRowsDeleted(row, row); |
| } |
| |
| /** |
| * Returns the number of rows in the model. |
| * |
| * @return The row count. |
| */ |
| public int getRowCount() |
| { |
| return dataVector.size(); |
| } |
| |
| /** |
| * Returns the number of columns in the model. |
| * |
| * @return The column count. |
| */ |
| public int getColumnCount() |
| { |
| return columnIdentifiers == null ? 0 : columnIdentifiers.size(); |
| } |
| |
| /** |
| * Get the name of the column. If the column has the column identifier set, |
| * the return value is the result of the .toString() method call on that |
| * identifier. If the identifier is not explicitly set, the returned value |
| * is calculated by {@link AbstractTableModel#getColumnName(int)}. |
| * |
| * @param column the column index. |
| * |
| * @return The column name. |
| */ |
| public String getColumnName(int column) |
| { |
| String result = ""; |
| if (columnIdentifiers == null) |
| result = super.getColumnName(column); |
| else |
| { |
| if (column < getColumnCount()) |
| { |
| checkSize(); |
| Object id = columnIdentifiers.get(column); |
| if (id != null) |
| result = id.toString(); |
| else |
| result = super.getColumnName(column); |
| } |
| else |
| result = super.getColumnName(column); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns <code>true</code> if the specified cell can be modified, and |
| * <code>false</code> otherwise. For this implementation, the method |
| * always returns <code>true</code>. |
| * |
| * @param row the row index. |
| * @param column the column index. |
| * |
| * @return <code>true</code> in all cases. |
| */ |
| public boolean isCellEditable(int row, int column) |
| { |
| return true; |
| } |
| |
| /** |
| * Returns the value at the specified cell in the table. |
| * |
| * @param row the row index. |
| * @param column the column index. |
| * |
| * @return The value (<code>Object</code>, possibly <code>null</code>) at |
| * the specified cell in the table. |
| */ |
| public Object getValueAt(int row, int column) |
| { |
| return ((Vector) dataVector.get(row)).get(column); |
| } |
| |
| /** |
| * Sets the value for the specified cell in the table and sends a |
| * {@link TableModelEvent} to all registered listeners. |
| * |
| * @param value the value (<code>Object</code>, <code>null</code> permitted). |
| * @param row the row index. |
| * @param column the column index. |
| */ |
| public void setValueAt(Object value, int row, int column) |
| { |
| ((Vector) dataVector.get(row)).set(column, value); |
| fireTableCellUpdated(row, column); |
| } |
| |
| /** |
| * Converts the data array to a <code>Vector</code>. |
| * |
| * @param data the data array (<code>null</code> permitted). |
| * |
| * @return A vector (or <code>null</code> if the data array |
| * is <code>null</code>). |
| */ |
| protected static Vector convertToVector(Object[] data) |
| { |
| if (data == null) |
| return null; |
| Vector vector = new Vector(data.length); |
| for (int i = 0; i < data.length; i++) |
| vector.add(data[i]); |
| return vector; |
| } |
| |
| /** |
| * Converts the data array to a <code>Vector</code> of rows. |
| * |
| * @param data the data array (<code>null</code> permitted). |
| * |
| * @return A vector (or <code>null</code> if the data array |
| * is <code>null</code>. |
| */ |
| protected static Vector convertToVector(Object[][] data) |
| { |
| if (data == null) |
| return null; |
| Vector vector = new Vector(data.length); |
| for (int i = 0; i < data.length; i++) |
| vector.add(convertToVector(data[i])); |
| return vector; |
| } |
| |
| /** |
| * This method adds some rows to <code>dataVector</code>. |
| * |
| * @param rowsToAdd number of rows to add |
| * @param nbColumns size of the added rows |
| */ |
| private void addExtraRows(int rowsToAdd, int nbColumns) |
| { |
| for (int i = 0; i < rowsToAdd; i++) |
| { |
| Vector tmp = new Vector(); |
| tmp.setSize(columnIdentifiers.size()); |
| dataVector.add(tmp); |
| } |
| } |
| |
| /** |
| * Checks the real columns/rows sizes against the ones returned by |
| * <code>getColumnCount()</code> and <code>getRowCount()</code>. |
| * If the supposed one are bigger, then we grow <code>columIdentifiers</code> |
| * and <code>dataVector</code> to their expected size. |
| */ |
| private void checkSize() |
| { |
| int columnCount = getColumnCount(); |
| int rowCount = getRowCount(); |
| |
| if (columnCount > columnIdentifiers.size()) |
| columnIdentifiers.setSize(columnCount); |
| |
| if (dataVector != null && rowCount > dataVector.size()) |
| { |
| int rowsToAdd = rowCount - dataVector.size(); |
| addExtraRows(rowsToAdd, columnCount); |
| } |
| } |
| } |