Revision: 1675 http://svn.sourceforge.net/spring-rich-c/?rev=1675&view=rev Author: kevinstembridge Date: 2007-01-18 07:29:48 -0800 (Thu, 18 Jan 2007)
Log Message: ----------- Added javadoc and removed use of overridable method in constructor Modified Paths: -------------- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/table/BaseTableModel.java Modified: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/table/BaseTableModel.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/table/BaseTableModel.java 2007-01-16 20:22:31 UTC (rev 1674) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/table/BaseTableModel.java 2007-01-18 15:29:48 UTC (rev 1675) @@ -22,27 +22,59 @@ import javax.swing.table.AbstractTableModel; import org.springframework.binding.value.support.ObservableList; +import org.springframework.richclient.util.Assert; /** + * A skeleton [EMAIL PROTECTED] TableModel} implementation that adds to the [EMAIL PROTECTED] AbstractTableModel} class + * from the core Java API by providing the functionality to manage the underlying collection + * of data for the table. + * * @author Keith Donald */ public abstract class BaseTableModel extends AbstractTableModel implements MutableTableModel { + private Class[] columnClasses; + /** The names for the column headers. Must never be null. */ private String[] columnNames; + /** + * The collection of objects that represent the rows of the table. + * Class invariant; this must never be null. + */ private List rows; private boolean rowNumbers = true; + /** + * Creates a new uninitialized [EMAIL PROTECTED] BaseTableModel}. + */ public BaseTableModel() { - this(new ArrayList()); + this.rows = new ArrayList(); } + /** + * Creates a new [EMAIL PROTECTED] BaseTableModel} containing the given collection of rows. + * + * @param rows The rows of the table model. May be null or empty. + */ public BaseTableModel(List rows) { - setRows(rows); + if (rows == null) { + this.rows = new ArrayList(); + } + else { + this.rows = rows; + } + } + /** + * Overwrites the existing table rows with the given collection and fires an appropriate event + * to all registered listeners. + * + * @param rows The collection of rows that will overwrite the existing collection. May be + * null or empty. + */ public void setRows(List rows) { // first check null, if somehow field was null it may not return (in second if) if (rows == null) { @@ -55,6 +87,12 @@ fireTableDataChanged(); } + /** + * Sets the flag that indicates whether or not row numbers are to appear in the first column + * of the displayed table. + * + * @param rowNumbers The flag to display row numbers in the first column. + */ public void setRowNumbers(boolean rowNumbers) { if (this.rowNumbers != rowNumbers) { this.rowNumbers = rowNumbers; @@ -63,64 +101,122 @@ } } + /** + * Returns true if row numbers are to appear in the first column of the displayed table (default + * is true). + * + * @return The flag to show row numbers in the first column of the displayed table. + */ public boolean hasRowNumbers() { return rowNumbers; } + /** + * Creates the required column information based on the value provided by the + * [EMAIL PROTECTED] #createColumnClasses()} and [EMAIL PROTECTED] #createColumnNames()} methods. + */ protected void createColumnInfo() { - Class[] columnClasses = createColumnClasses(); - String[] columnNames = createColumnNames(); + + Class[] newColumnClasses = createColumnClasses(); + String[] newColumnNames = createColumnNames(); + if (rowNumbers) { // modify columns to add rowNo as first column - this.columnClasses = new Class[columnClasses.length + 1]; + this.columnClasses = new Class[newColumnClasses.length + 1]; this.columnClasses[0] = Integer.class; - System.arraycopy(columnClasses, 0, this.columnClasses, 1, columnClasses.length); + System.arraycopy(newColumnClasses, 0, this.columnClasses, 1, newColumnClasses.length); - this.columnNames = new String[columnNames.length + 1]; + this.columnNames = new String[newColumnNames.length + 1]; this.columnNames[0] = " "; - System.arraycopy(columnNames, 0, this.columnNames, 1, columnNames.length); + System.arraycopy(newColumnNames, 0, this.columnNames, 1, newColumnNames.length); } else { // take columns as they are - this.columnClasses = columnClasses; - this.columnNames = columnNames; + this.columnClasses = newColumnClasses; + this.columnNames = newColumnNames; } + } + /** + * [EMAIL PROTECTED] + */ public int getRowCount() { return rows.size(); } + /** + * [EMAIL PROTECTED] + */ public int getColumnCount() { return columnNames.length; } + /** + * Returns the number of columns, excluding the column that displays row numbers if present. + * + * @return The number of columns, not counting the row number column if present. + */ public int getDataColumnCount() { return rowNumbers ? columnNames.length - 1 : getColumnCount(); } + /** + * Returns the type of the object to be displayed in the given column. + * + * @param columnIndex The zero-based index of the column whose type will be returned. + * + * @throws IndexOutOfBoundsException if [EMAIL PROTECTED] columnIndex} is not within the bounds of the + * column range for a row of the table. + */ public Class getColumnClass(int columnIndex) { return columnClasses[columnIndex]; } + /** + * Returns the name to be displayed in the header for the column at the given position. + * + * @param columnIndex The zero-based index of the column whose name will be returned. + * + * @throws IndexOutOfBoundsException if [EMAIL PROTECTED] columnInde} is not within the bounds of the + * column range for a row of the table. + */ public String getColumnName(int columnIndex) { return columnNames[columnIndex]; } + /** + * Returns the array of column headers. + * + * @return The array of column headers, never null. + */ public String[] getColumnHeaders() { return columnNames; } + /** + * Returns the array of column headers other than the column displaying the row numbers, + * if present. + * + * @return The column headers, not including the row number column. Never null. + */ public String[] getDataColumnHeaders() { + String[] headers = getColumnHeaders(); - if (!hasRowNumbers()) + + if (!hasRowNumbers()) { return headers; + } String[] dataHeaders = new String[headers.length - 1]; System.arraycopy(headers, 1, dataHeaders, 0, headers.length - 1); return dataHeaders; + } + /** + * [EMAIL PROTECTED] + */ public Object getValueAt(int rowIndex, int columnIndex) { if (rowNumbers) { if (columnIndex == 0) { @@ -131,22 +227,48 @@ return getValueAtInternal(rows.get(rowIndex), columnIndex); } + /** + * Subclasses must implement this method to return the value at the given column index for + * the given object. + * + * @param row The object representing a row of data from the table. + * @param columnIndex The column index of the value to be returned. + * @return The value at the given index for the given object. May be null. + */ protected abstract Object getValueAtInternal(Object row, int columnIndex); + /** + * [EMAIL PROTECTED] + */ + //FIXME this method should probably become a template method by making it final public boolean isCellEditable(int rowIndex, int columnIndex) { + if (rowNumbers) { if (columnIndex == 0) { return false; } columnIndex--; } + return isCellEditableInternal(rows.get(rowIndex), columnIndex); + } + /** + * Subclasses may override this method to determine if the cell at the specified row and + * column position can be edited. Default behaviour is to always return false. + * + * @param row The object representing the table row. + * @param columnIndex The zero-based index of the column to be checked. + * @return true if the given cell is editable, false otherwise. + */ protected boolean isCellEditableInternal(Object row, int columnIndex) { return false; } + /** + * [EMAIL PROTECTED] + */ public void setValueAt(Object value, int rowIndex, int columnIndex) { if (rowNumbers) { columnIndex--; @@ -158,64 +280,202 @@ fireTableCellUpdated(rowIndex, columnIndex); } + /** + * Subclasses may implement this method to set the given value on the property at the given + * column index of the given row object. The default implementation is to do nothing. + * + * @param value The value to be set. + * @param row The object representing the row in the table. + * @param columnIndex The column position of the property on the given row object. + */ protected void setValueAtInternal(Object value, Object row, int columnIndex) { + //do nothing } + /** + * Returns the object representing the row at the given zero-based index. + * + * @param rowIndex The zero-based index of the row whose object should be returned. + * @return The object for the given row. + * + * @throws IndexOutOfBoundsException if [EMAIL PROTECTED] rowIndex} is not within the bounds of the + * collection of rows for this table model. + */ public Object getRow(int rowIndex) { return rows.get(rowIndex); } + /** + * Returns the collection of all the rows in this table model. + * + * @return The collection rows. The collection may be empty but will never be null. + */ public List getRows() { return rows; } + /** + * Returns the collection of data from the given column of each row in the table model. + * + * @param column The zero-based index of the column whose data should be returned. + * @return The collection of data from the given column. + * + * @throws IndexOutOfBoundsException if the given column is not within the bounds of the + * number of columns for the rows in this table model. + */ public List getColumnData(int column) { - if (getColumnCount() == 1) + + int columnCount = getColumnCount(); + + if (column < 0 || column >= columnCount) { + throw new IndexOutOfBoundsException("The given column index [" + + column + + "] is outside the bounds of the number of columns [" + + columnCount + + "] in the rows of this table model."); + } + + if (columnCount == 1) { return rows; + } List colData = new ArrayList(getRowCount()); + for (int i = 0; i < getRowCount(); i++) { colData.add(getValueAt(i, column)); } + return colData; + } - public int rowOf(Object o) { - return rows.indexOf(o); + /** + * Returns the index of the first row containing the specified element, or -1 if this table + * model does not contain this element. + * + * @param obj The object whose row number will be returned. + * @return The index of the first row containing the given object, or -1 if the table model + * does not contain the object. + */ + public int rowOf(Object obj) { + + if (obj == null) { + return -1; + } + + return rows.indexOf(obj); + } + /** + * [EMAIL PROTECTED] + */ public void addRow(Object row) { + + Assert.required(row, "row"); + this.rows.add(row); int index = this.rows.size() - 1; fireTableRowsInserted(index, index); } - public void addRows(List rows) { - if (rows == null) { - throw new NullPointerException(); + /** + * [EMAIL PROTECTED] + */ + public void addRows(List newRows) { + Assert.required(newRows, "newRows"); + + if (newRows.isEmpty()) { + return; } + int firstRow = this.rows.size(); - this.rows.addAll(rows); + this.rows.addAll(newRows); int lastRow = this.rows.size() - 1; fireTableRowsInserted(firstRow, lastRow); } + /** + * [EMAIL PROTECTED] + */ public void remove(int index) { this.rows.remove(index); fireTableRowsDeleted(index, index); } + /** + * [EMAIL PROTECTED] + */ public void remove(int firstIndex, int lastIndex) { + + if (lastIndex < firstIndex) { + throw new IllegalArgumentException("lastIndex [" + + lastIndex + + "] cannot be less than firstIndex [" + + firstIndex + + "]"); + } + + if (firstIndex < 0 || firstIndex >= this.rows.size()) { + throw new IndexOutOfBoundsException("The specified starting index [" + + firstIndex + + "] is outside the bounds of the rows collection " + + "which only has [" + + this.rows.size() + + "] elements."); + } + + if (lastIndex >= this.rows.size()) { + throw new IndexOutOfBoundsException("The specified end index [" + + lastIndex + + "] is outside the bounds of the rows collection " + + "which only has [" + + this.rows.size() + + "] elements."); + } + int rowCount = lastIndex - firstIndex + 1; + for (int i = 0; i < rowCount; i++) { rows.remove(firstIndex); } + fireTableRowsDeleted(firstIndex, lastIndex); + } - // must sort the indexes first!!! + /** + * [EMAIL PROTECTED] + */ public void remove(int[] indexes) { + + Assert.required(indexes, "indexes"); + + if (indexes.length == 0) { + return; + } + + // must sort the indexes first!!! Arrays.sort(indexes); + + if (indexes[0] < 0 || indexes[0] >= this.rows.size()) { + throw new IndexOutOfBoundsException("The specified index [" + + indexes[0] + + "] is outside the bounds of the rows collection " + + "which only has [" + + this.rows.size() + + "] elements."); + } + + if ((indexes[indexes.length -1]) >= this.rows.size()) { + throw new IndexOutOfBoundsException("The specified end index [" + + indexes[indexes.length -1] + + "] is outside the bounds of the rows collection " + + "which only has [" + + this.rows.size() + + "] elements."); + } + int firstIndex = indexes[0]; int lastIndex = indexes[0]; int i = 0; @@ -237,21 +497,46 @@ remove(firstIndex - shift, lastIndex - shift); } + /** + * [EMAIL PROTECTED] + */ public void clear() { this.rows.clear(); fireTableDataChanged(); } + /** + * Returns the array of class types for the columns displayed by this table model. + * + * @return The array of column class types, never null. + */ protected Class[] getColumnClasses() { return columnClasses; } + /** + * Returns the array of column headers for the columns displayed by this table model. + * + * @return The array of column headers, never null. + */ protected String[] getColumnNames() { return columnNames; } + /** + * Subclasses must implement this method to return the array of class types for the columns + * displayed by this table model. + * + * @return The array of column class types, never null. + */ protected abstract Class[] createColumnClasses(); + /** + * Subclasses must implement this method to return the array of column headers for the + * columns to be displayed by this table model. + * + * @return The array of column headers, never null. + */ protected abstract String[] createColumnNames(); -} \ No newline at end of file +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ spring-rich-c-cvs mailing list spring-rich-c-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spring-rich-c-cvs