GNU Classpath (0.20) | |
Frames | No Frames |
1: /* DefaultTableModel.java -- 2: Copyright (C) 2002, 2004, 2005, Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 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. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 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. */ 37: 38: 39: package javax.swing.table; 40: 41: import java.io.Serializable; 42: import java.util.Vector; 43: 44: import javax.swing.event.TableModelEvent; 45: 46: /** 47: * A two dimensional data structure used to store <code>Object</code> 48: * instances, usually for display in a <code>JTable</code> component. 49: * 50: * @author Andrew Selkirk 51: */ 52: public class DefaultTableModel extends AbstractTableModel 53: implements Serializable 54: { 55: static final long serialVersionUID = 6680042567037222321L; 56: 57: /** 58: * Storage for the rows in the table (each row is itself 59: * a <code>Vector</code>). 60: */ 61: protected Vector dataVector; 62: 63: /** 64: * Storage for the column identifiers. 65: */ 66: protected Vector columnIdentifiers; 67: 68: /** 69: * Creates an empty table with zero rows and zero columns. 70: */ 71: public DefaultTableModel() 72: { 73: this(0, 0); 74: } 75: 76: /** 77: * Creates a new table with the specified number of rows and columns. 78: * All cells in the table are initially empty (set to <code>null</code>). 79: * 80: * @param numRows the number of rows. 81: * @param numColumns the number of columns. 82: */ 83: public DefaultTableModel(int numRows, int numColumns) 84: { 85: Vector defaultNames = new Vector(numColumns); 86: Vector data = new Vector(numRows); 87: for (int i = 0; i < numColumns; i++) 88: { 89: defaultNames.add(super.getColumnName(i)); 90: } 91: for (int r = 0; r < numRows; r++) 92: { 93: Vector tmp = new Vector(numColumns); 94: tmp.setSize(numColumns); 95: data.add(tmp); 96: } 97: setDataVector(data, defaultNames); 98: } 99: 100: /** 101: * Creates a new table with the specified column names and number of 102: * rows. The number of columns is determined by the number of column 103: * names supplied. 104: * 105: * @param columnNames the column names. 106: * @param numRows the number of rows. 107: */ 108: public DefaultTableModel(Vector columnNames, int numRows) 109: { 110: if (numRows < 0) 111: throw new IllegalArgumentException("numRows < 0"); 112: Vector data = new Vector(); 113: int numColumns = 0; 114: 115: if (columnNames != null) 116: numColumns = columnNames.size(); 117: 118: while (0 < numRows--) 119: { 120: Vector rowData = new Vector(); 121: rowData.setSize(numColumns); 122: data.add(rowData); 123: } 124: setDataVector(data, columnNames); 125: } 126: 127: /** 128: * Creates a new table with the specified column names and row count. 129: * 130: * @param columnNames the column names. 131: * @param numRows the number of rows. 132: */ 133: public DefaultTableModel(Object[] columnNames, int numRows) 134: { 135: this(convertToVector(columnNames), numRows); 136: } 137: 138: /** 139: * Creates a new table with the specified data values and column names. 140: * 141: * @param data the data values. 142: * @param columnNames the column names. 143: */ 144: public DefaultTableModel(Vector data, Vector columnNames) 145: { 146: setDataVector(data, columnNames); 147: } 148: 149: /** 150: * Creates a new table with the specified data values and column names. 151: * 152: * @param data the data values. 153: * @param columnNames the column names. 154: */ 155: public DefaultTableModel(Object[][] data, Object[] columnNames) 156: { 157: this(convertToVector(data), convertToVector(columnNames)); 158: } 159: 160: /** 161: * Returns the vector containing the row data for the table. 162: * 163: * @return The data vector. 164: */ 165: public Vector getDataVector() 166: { 167: return dataVector; 168: } 169: 170: /** 171: * Sets the data and column identifiers for the table. The data vector 172: * contains a <code>Vector</code> for each row in the table - if the 173: * number of objects in each row does not match the number of column 174: * names specified, the row data is truncated or expanded (by adding 175: * <code>null</code> values) as required. 176: * 177: * @param data the data for the table (a vector of row vectors). 178: * @param columnNames the column names. 179: * 180: * @throws NullPointerException if either argument is <code>null</code>. 181: */ 182: public void setDataVector(Vector data, Vector columnNames) 183: { 184: if (data == null) 185: dataVector = new Vector(); 186: else 187: dataVector = data; 188: setColumnIdentifiers(columnNames); 189: } 190: 191: /** 192: * Sets the data and column identifiers for the table. 193: * 194: * @param data the data for the table. 195: * @param columnNames the column names. 196: * 197: * @throws NullPointerException if either argument is <code>null</code>. 198: */ 199: public void setDataVector(Object[][] data, Object[] columnNames) 200: { 201: setDataVector(convertToVector(data), 202: convertToVector(columnNames)); 203: } 204: 205: /** 206: * Sends the specified <code>event</code> to all registered listeners. 207: * This method is equivalent to 208: * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}. 209: * 210: * @param event the event. 211: */ 212: public void newDataAvailable(TableModelEvent event) 213: { 214: fireTableChanged(event); 215: } 216: 217: /** 218: * Sends the specified <code>event</code> to all registered listeners. 219: * This method is equivalent to 220: * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}. 221: * 222: * @param event the event. 223: */ 224: public void newRowsAdded(TableModelEvent event) 225: { 226: fireTableChanged(event); 227: } 228: 229: /** 230: * Sends the specified <code>event</code> to all registered listeners. 231: * This method is equivalent to 232: * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}. 233: * 234: * @param event the event. 235: */ 236: public void rowsRemoved(TableModelEvent event) 237: { 238: fireTableChanged(event); 239: } 240: 241: /** 242: * Sets the column identifiers, updates the data rows (truncating 243: * or padding each row with <code>null</code> values) to match the 244: * number of columns, and sends a {@link TableModelEvent} to all 245: * registered listeners. 246: * 247: * @param columnIdentifiers the column identifiers. 248: */ 249: public void setColumnIdentifiers(Vector columnIdentifiers) 250: { 251: this.columnIdentifiers = columnIdentifiers; 252: setColumnCount((columnIdentifiers == null ? 0 : columnIdentifiers.size())); 253: } 254: 255: /** 256: * Sets the column identifiers, updates the data rows (truncating 257: * or padding each row with <code>null</code> values) to match the 258: * number of columns, and sends a {@link TableModelEvent} to all 259: * registered listeners. 260: * 261: * @param columnIdentifiers the column identifiers. 262: */ 263: public void setColumnIdentifiers(Object[] columnIdentifiers) 264: { 265: setColumnIdentifiers(convertToVector(columnIdentifiers)); 266: } 267: 268: /** 269: * This method is obsolete, use {@link #setRowCount(int)} instead. 270: * 271: * @param numRows the number of rows. 272: */ 273: public void setNumRows(int numRows) 274: { 275: setRowCount(numRows); 276: } 277: 278: /** 279: * Sets the number of rows in the table. If <code>rowCount</code> is less 280: * than the current number of rows in the table, rows are discarded. 281: * If <code>rowCount</code> is greater than the current number of rows in 282: * the table, new (empty) rows are added. 283: * 284: * @param rowCount the row count. 285: */ 286: public void setRowCount(int rowCount) 287: { 288: int existingRowCount = dataVector.size(); 289: if (rowCount < existingRowCount) 290: { 291: dataVector.setSize(rowCount); 292: fireTableRowsDeleted(rowCount,existingRowCount-1); 293: } 294: else 295: { 296: int rowsToAdd = rowCount - existingRowCount; 297: for (int i = 0; i < rowsToAdd; i++) 298: { 299: Vector tmp = new Vector(); 300: tmp.setSize(columnIdentifiers.size()); 301: dataVector.add(tmp); 302: } 303: fireTableRowsInserted(existingRowCount,rowCount-1); 304: } 305: } 306: 307: /** 308: * Sets the number of columns in the table. Existing rows are truncated 309: * or padded with <code>null</code> values to match the new column count. 310: * A {@link TableModelEvent} is sent to all registered listeners. 311: * 312: * @param columnCount the column count. 313: */ 314: public void setColumnCount(int columnCount) 315: { 316: for (int i = 0; i < dataVector.size(); ++i) 317: { 318: ((Vector) dataVector.get(i)).setSize(columnCount); 319: } 320: if (columnIdentifiers != null) 321: columnIdentifiers.setSize(columnCount); 322: fireTableStructureChanged(); 323: } 324: 325: /** 326: * Adds a column with the specified name to the table. All cell values 327: * for the column are initially set to <code>null</code>. 328: * 329: * @param columnName the column name (<code>null</code> permitted). 330: */ 331: public void addColumn(Object columnName) 332: { 333: addColumn(columnName, (Object[]) null); 334: } 335: 336: /** 337: * Adds a column with the specified name and data values to the table. 338: * 339: * @param columnName the column name (<code>null</code> permitted). 340: * @param columnData the column data. 341: */ 342: public void addColumn(Object columnName, Vector columnData) 343: { 344: Object[] dataArray = null; 345: if (columnData != null) 346: { 347: int rowCount = dataVector.size(); 348: if (columnData.size() < rowCount) 349: columnData.setSize(rowCount); 350: dataArray = columnData.toArray(); 351: } 352: addColumn(columnName, dataArray); 353: } 354: 355: /** 356: * Adds a column with the specified name and data values to the table. 357: * 358: * @param columnName the column name (<code>null</code> permitted). 359: * @param columnData the column data. 360: */ 361: public void addColumn(Object columnName, Object[] columnData) { 362: if (columnData != null) 363: { 364: // check columnData array for cases where the number of items 365: // doesn't match the number of rows in the existing table 366: if (columnData.length > dataVector.size()) 367: { 368: int rowsToAdd = columnData.length - dataVector.size(); 369: for (int i = 0; i < rowsToAdd; i++) 370: { 371: Vector tmp = new Vector(); 372: tmp.setSize(columnIdentifiers.size()); 373: dataVector.add(tmp); 374: } 375: } 376: else if (columnData.length < dataVector.size()) 377: { 378: Object[] tmp = new Object[dataVector.size()]; 379: System.arraycopy(columnData, 0, tmp, 0, columnData.length); 380: columnData = tmp; 381: } 382: } 383: for (int i = 0; i < dataVector.size(); ++i) 384: { 385: ((Vector) dataVector.get(i)).add(columnData == null ? null : columnData[i]); 386: } 387: columnIdentifiers.add(columnName); 388: fireTableStructureChanged(); 389: } 390: 391: /** 392: * Adds a new row containing the specified data to the table and sends a 393: * {@link TableModelEvent} to all registered listeners. 394: * 395: * @param rowData the row data (<code>null</code> permitted). 396: */ 397: public void addRow(Vector rowData) { 398: int rowIndex = dataVector.size(); 399: dataVector.add(rowData); 400: newRowsAdded(new TableModelEvent( 401: this, rowIndex, rowIndex, -1, TableModelEvent.INSERT) 402: ); 403: } 404: 405: /** 406: * Adds a new row containing the specified data to the table and sends a 407: * {@link TableModelEvent} to all registered listeners. 408: * 409: * @param rowData the row data (<code>null</code> permitted). 410: */ 411: public void addRow(Object[] rowData) { 412: addRow(convertToVector(rowData)); 413: } 414: 415: /** 416: * Inserts a new row into the table. 417: * 418: * @param row the row index. 419: * @param rowData the row data. 420: */ 421: public void insertRow(int row, Vector rowData) { 422: dataVector.add(row, rowData); 423: fireTableRowsInserted(row,row); 424: } 425: 426: /** 427: * Inserts a new row into the table. 428: * 429: * @param row the row index. 430: * @param rowData the row data. 431: */ 432: public void insertRow(int row, Object[] rowData) { 433: insertRow(row, convertToVector(rowData)); 434: } 435: 436: /** 437: * Moves the rows from <code>startIndex</code> to <code>endIndex</code> 438: * (inclusive) to the specified row. 439: * 440: * @param startIndex the start row. 441: * @param endIndex the end row. 442: * @param toIndex the row to move to. 443: */ 444: public void moveRow(int startIndex, int endIndex, int toIndex) { 445: Vector removed = new Vector(); 446: for (int i = endIndex; i >= startIndex; i--) 447: { 448: removed.add(this.dataVector.remove(i)); 449: } 450: for (int i = 0; i <= endIndex - startIndex; i++) 451: { 452: dataVector.insertElementAt(removed.get(i), toIndex); 453: } 454: int firstRow = Math.min(startIndex, toIndex); 455: int lastRow = Math.max(endIndex, toIndex + (endIndex - startIndex)); 456: fireTableRowsUpdated(firstRow, lastRow); 457: } 458: 459: /** 460: * Removes a row from the table and sends a {@link TableModelEvent} to 461: * all registered listeners. 462: * 463: * @param row the row index. 464: */ 465: public void removeRow(int row) { 466: dataVector.remove(row); 467: fireTableRowsDeleted(row,row); 468: } 469: 470: /** 471: * Returns the number of rows in the model. 472: * 473: * @return The row count. 474: */ 475: public int getRowCount() { 476: return dataVector.size(); 477: } 478: 479: /** 480: * Returns the number of columns in the model. 481: * 482: * @return The column count. 483: */ 484: public int getColumnCount() { 485: return (columnIdentifiers == null ? 0 : columnIdentifiers.size()); 486: } 487: 488: /** 489: * Returns the name of the specified column. 490: * 491: * @param column the column index. 492: * 493: * @return The column name. 494: */ 495: public String getColumnName(int column) { 496: String result = ""; 497: if (columnIdentifiers == null) 498: result = super.getColumnName(column); 499: else 500: { 501: if (column < getColumnCount()) 502: { 503: Object id = columnIdentifiers.get(column); 504: if (id != null) 505: result = id.toString(); 506: else 507: result = super.getColumnName(column); 508: } 509: else 510: result = super.getColumnName(column); 511: } 512: return result; 513: } 514: 515: /** 516: * Returns <code>true</code> if the specified cell can be modified, and 517: * <code>false</code> otherwise. For this implementation, the method 518: * always returns <code>true</code>. 519: * 520: * @param row the row index. 521: * @param column the column index. 522: * 523: * @return <code>true</code> in all cases. 524: */ 525: public boolean isCellEditable(int row, int column) { 526: return true; 527: } 528: 529: /** 530: * Returns the value at the specified cell in the table. 531: * 532: * @param row the row index. 533: * @param column the column index. 534: * 535: * @return The value (<code>Object</code>, possibly <code>null</code>) at 536: * the specified cell in the table. 537: */ 538: public Object getValueAt(int row, int column) { 539: return ((Vector) dataVector.get(row)).get(column); 540: } 541: 542: /** 543: * Sets the value for the specified cell in the table and sends a 544: * {@link TableModelEvent} to all registered listeners. 545: * 546: * @param value the value (<code>Object</code>, <code>null</code> permitted). 547: * @param row the row index. 548: * @param column the column index. 549: */ 550: public void setValueAt(Object value, int row, int column) { 551: ((Vector) dataVector.get(row)).set(column, value); 552: fireTableCellUpdated(row,column); 553: } 554: 555: /** 556: * Converts the data array to a <code>Vector</code>. 557: * 558: * @param data the data array (<code>null</code> permitted). 559: * 560: * @return A vector (or <code>null</code> if the data array 561: * is <code>null</code>). 562: */ 563: protected static Vector convertToVector(Object[] data) { 564: if (data == null) 565: return null; 566: Vector vector = new Vector(data.length); 567: for (int i = 0; i < data.length; i++) 568: vector.add(data[i]); 569: return vector; 570: } 571: 572: /** 573: * Converts the data array to a <code>Vector</code> of rows. 574: * 575: * @param data the data array (<code>null</code> permitted). 576: * 577: * @return A vector (or <code>null</code> if the data array 578: * is <code>null</code>. 579: */ 580: protected static Vector convertToVector(Object[][] data) { 581: if (data == null) 582: return null; 583: Vector vector = new Vector(data.length); 584: for (int i = 0; i < data.length; i++) 585: vector.add(convertToVector(data[i])); 586: return vector; 587: } 588: }
GNU Classpath (0.20) |