GNU Classpath (0.91) | |
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: addExtraRows(rowsToAdd, columnIdentifiers.size()); 298: fireTableRowsInserted(existingRowCount,rowCount-1); 299: } 300: } 301: 302: /** 303: * Sets the number of columns in the table. Existing rows are truncated 304: * or padded with <code>null</code> values to match the new column count. 305: * A {@link TableModelEvent} is sent to all registered listeners. 306: * 307: * @param columnCount the column count. 308: */ 309: public void setColumnCount(int columnCount) 310: { 311: for (int i = 0; i < dataVector.size(); ++i) 312: { 313: ((Vector) dataVector.get(i)).setSize(columnCount); 314: } 315: if (columnIdentifiers != null) 316: columnIdentifiers.setSize(columnCount); 317: fireTableStructureChanged(); 318: } 319: 320: /** 321: * Adds a column with the specified name to the table. All cell values 322: * for the column are initially set to <code>null</code>. 323: * 324: * @param columnName the column name (<code>null</code> permitted). 325: */ 326: public void addColumn(Object columnName) 327: { 328: addColumn(columnName, (Object[]) null); 329: } 330: 331: /** 332: * Adds a column with the specified name and data values to the table. 333: * 334: * @param columnName the column name (<code>null</code> permitted). 335: * @param columnData the column data. 336: */ 337: public void addColumn(Object columnName, Vector columnData) 338: { 339: Object[] dataArray = null; 340: if (columnData != null) 341: { 342: int rowCount = dataVector.size(); 343: if (columnData.size() < rowCount) 344: columnData.setSize(rowCount); 345: dataArray = columnData.toArray(); 346: } 347: addColumn(columnName, dataArray); 348: } 349: 350: /** 351: * Adds a column with the specified name and data values to the table. 352: * 353: * @param columnName the column name (<code>null</code> permitted). 354: * @param columnData the column data. 355: */ 356: public void addColumn(Object columnName, Object[] columnData) { 357: if (columnData != null) 358: { 359: // check columnData array for cases where the number of items 360: // doesn't match the number of rows in the existing table 361: if (columnData.length > dataVector.size()) 362: { 363: int rowsToAdd = columnData.length - dataVector.size(); 364: addExtraRows(rowsToAdd, columnIdentifiers.size()); 365: } 366: else if (columnData.length < dataVector.size()) 367: { 368: Object[] tmp = new Object[dataVector.size()]; 369: System.arraycopy(columnData, 0, tmp, 0, columnData.length); 370: columnData = tmp; 371: } 372: } 373: for (int i = 0; i < dataVector.size(); ++i) 374: { 375: ((Vector) dataVector.get(i)).add(columnData == null ? null : columnData[i]); 376: } 377: columnIdentifiers.add(columnName); 378: fireTableStructureChanged(); 379: } 380: 381: /** 382: * Adds a new row containing the specified data to the table and sends a 383: * {@link TableModelEvent} to all registered listeners. 384: * 385: * @param rowData the row data (<code>null</code> permitted). 386: */ 387: public void addRow(Vector rowData) { 388: int rowIndex = dataVector.size(); 389: dataVector.add(rowData); 390: newRowsAdded(new TableModelEvent( 391: this, rowIndex, rowIndex, -1, TableModelEvent.INSERT) 392: ); 393: } 394: 395: /** 396: * Adds a new row containing the specified data to the table and sends a 397: * {@link TableModelEvent} to all registered listeners. 398: * 399: * @param rowData the row data (<code>null</code> permitted). 400: */ 401: public void addRow(Object[] rowData) { 402: addRow(convertToVector(rowData)); 403: } 404: 405: /** 406: * Inserts a new row into the table. 407: * 408: * @param row the row index. 409: * @param rowData the row data. 410: */ 411: public void insertRow(int row, Vector rowData) { 412: dataVector.add(row, rowData); 413: fireTableRowsInserted(row,row); 414: } 415: 416: /** 417: * Inserts a new row into the table. 418: * 419: * @param row the row index. 420: * @param rowData the row data. 421: */ 422: public void insertRow(int row, Object[] rowData) { 423: insertRow(row, convertToVector(rowData)); 424: } 425: 426: /** 427: * Moves the rows from <code>startIndex</code> to <code>endIndex</code> 428: * (inclusive) to the specified row. 429: * 430: * @param startIndex the start row. 431: * @param endIndex the end row. 432: * @param toIndex the row to move to. 433: */ 434: public void moveRow(int startIndex, int endIndex, int toIndex) { 435: Vector removed = new Vector(); 436: for (int i = endIndex; i >= startIndex; i--) 437: { 438: removed.add(this.dataVector.remove(i)); 439: } 440: for (int i = 0; i <= endIndex - startIndex; i++) 441: { 442: dataVector.insertElementAt(removed.get(i), toIndex); 443: } 444: int firstRow = Math.min(startIndex, toIndex); 445: int lastRow = Math.max(endIndex, toIndex + (endIndex - startIndex)); 446: fireTableRowsUpdated(firstRow, lastRow); 447: } 448: 449: /** 450: * Removes a row from the table and sends a {@link TableModelEvent} to 451: * all registered listeners. 452: * 453: * @param row the row index. 454: */ 455: public void removeRow(int row) { 456: dataVector.remove(row); 457: fireTableRowsDeleted(row,row); 458: } 459: 460: /** 461: * Returns the number of rows in the model. 462: * 463: * @return The row count. 464: */ 465: public int getRowCount() { 466: return dataVector.size(); 467: } 468: 469: /** 470: * Returns the number of columns in the model. 471: * 472: * @return The column count. 473: */ 474: public int getColumnCount() { 475: return (columnIdentifiers == null ? 0 : columnIdentifiers.size()); 476: } 477: 478: /** 479: * Get the name of the column. If the column has the column identifier set, 480: * the return value is the result of the .toString() method call on that 481: * identifier. If the identifier is not explicitly set, the returned value 482: * is calculated by {@link AbstractTableModel#getColumnName(int)}. 483: * 484: * @param column the column index. 485: * 486: * @return The column name. 487: */ 488: public String getColumnName(int column) { 489: String result = ""; 490: if (columnIdentifiers == null) 491: result = super.getColumnName(column); 492: else 493: { 494: if (column < getColumnCount()) 495: { 496: checkSize(); 497: Object id = columnIdentifiers.get(column); 498: if (id != null) 499: result = id.toString(); 500: else 501: result = super.getColumnName(column); 502: } 503: else 504: result = super.getColumnName(column); 505: } 506: return result; 507: } 508: 509: /** 510: * Returns <code>true</code> if the specified cell can be modified, and 511: * <code>false</code> otherwise. For this implementation, the method 512: * always returns <code>true</code>. 513: * 514: * @param row the row index. 515: * @param column the column index. 516: * 517: * @return <code>true</code> in all cases. 518: */ 519: public boolean isCellEditable(int row, int column) { 520: return true; 521: } 522: 523: /** 524: * Returns the value at the specified cell in the table. 525: * 526: * @param row the row index. 527: * @param column the column index. 528: * 529: * @return The value (<code>Object</code>, possibly <code>null</code>) at 530: * the specified cell in the table. 531: */ 532: public Object getValueAt(int row, int column) { 533: return ((Vector) dataVector.get(row)).get(column); 534: } 535: 536: /** 537: * Sets the value for the specified cell in the table and sends a 538: * {@link TableModelEvent} to all registered listeners. 539: * 540: * @param value the value (<code>Object</code>, <code>null</code> permitted). 541: * @param row the row index. 542: * @param column the column index. 543: */ 544: public void setValueAt(Object value, int row, int column) { 545: ((Vector) dataVector.get(row)).set(column, value); 546: fireTableCellUpdated(row,column); 547: } 548: 549: /** 550: * Converts the data array to a <code>Vector</code>. 551: * 552: * @param data the data array (<code>null</code> permitted). 553: * 554: * @return A vector (or <code>null</code> if the data array 555: * is <code>null</code>). 556: */ 557: protected static Vector convertToVector(Object[] data) { 558: if (data == null) 559: return null; 560: Vector vector = new Vector(data.length); 561: for (int i = 0; i < data.length; i++) 562: vector.add(data[i]); 563: return vector; 564: } 565: 566: /** 567: * Converts the data array to a <code>Vector</code> of rows. 568: * 569: * @param data the data array (<code>null</code> permitted). 570: * 571: * @return A vector (or <code>null</code> if the data array 572: * is <code>null</code>. 573: */ 574: protected static Vector convertToVector(Object[][] data) { 575: if (data == null) 576: return null; 577: Vector vector = new Vector(data.length); 578: for (int i = 0; i < data.length; i++) 579: vector.add(convertToVector(data[i])); 580: return vector; 581: } 582: 583: /** 584: * This method adds some rows to <code>dataVector</code>. 585: * 586: * @param rowsToAdd number of rows to add 587: * @param nbColumns size of the added rows 588: */ 589: private void addExtraRows(int rowsToAdd, int nbColumns) 590: { 591: for (int i = 0; i < rowsToAdd; i++) 592: { 593: Vector tmp = new Vector(); 594: tmp.setSize(columnIdentifiers.size()); 595: dataVector.add(tmp); 596: } 597: } 598: 599: /** 600: * Checks the real columns/rows sizes against the ones returned by 601: * <code>getColumnCount()</code> and <code>getRowCount()</code>. 602: * If the supposed one are bigger, then we grow <code>columIdentifiers</code> 603: * and <code>dataVector</code> to their expected size. 604: */ 605: private void checkSize() 606: { 607: int columnCount = getColumnCount(); 608: int rowCount = getRowCount(); 609: 610: if (columnCount > columnIdentifiers.size()) 611: columnIdentifiers.setSize(columnCount); 612: 613: if (rowCount > dataVector.size()) 614: { 615: int rowsToAdd = rowCount - dataVector.size(); 616: addExtraRows(rowsToAdd, columnCount); 617: } 618: } 619: }
GNU Classpath (0.91) |