001: package net.sourceforge.squirrel_sql.fw.datasetviewer;
002:
003: /*
004: * Copyright (C) 2001-2002 Colin Bell
005: * colbell@users.sourceforge.net
006: * Modifications copyright (C) 2001-2002 Johan Compagner
007: * jcompagner@j-com.nl
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: */
023:
024: import java.util.ArrayList;
025: import java.util.List;
026: import java.util.Arrays;
027:
028: import javax.swing.table.AbstractTableModel;
029:
030: public final class MyTableModel extends AbstractTableModel {
031: private static final long serialVersionUID = 5511368149198548935L;
032:
033: private List<Object[]> _data = new ArrayList<Object[]>();
034: private ColumnDisplayDefinition[] _colDefs = new ColumnDisplayDefinition[0];
035: private IDataSetTableControls _creator = null;
036:
037: MyTableModel(IDataSetTableControls creator) {
038: super ();
039: _creator = creator;
040: }
041:
042: /**
043: * Determine whether the cell is editable by asking the creator whether
044: * the table is editable or not
045: */
046: public boolean isCellEditable(int row, int col) {
047: // DataTypes may limit the initial data read from the DB, e.g. to minimize the
048: // time needed for the initial load of the table.
049: // To edit the contents of a cell, we require that the entire contents of the data
050: // element be present in the cell before editing.
051: // Therefore we ask the DataType if we need to re-read the data contents
052: // without limiting it, and do that read if needed. If there is a problem during the
053: // read (e.g. we cannot identify exactly one row in the DB matching the
054: // current row in the table), then the cell is not editable.
055: // The reverse is not true - if we succeed in reading the data, there may still
056: // be other reasons why we cannot edit it, so we need to check for it being editable
057: // after the read
058:
059: if (col == RowNumberTableColumn.ROW_NUMBER_MODEL_INDEX) {
060: return false;
061: }
062:
063: if (_creator.needToReRead(col, getValueAt(row, col))) {
064: StringBuffer message = new StringBuffer();
065: Object newValue = _creator.reReadDatum(_data.get(row), col,
066: message);
067: if (message.length() > 0) {
068: // there was a problem with the read
069: // It would be nice to report this to the user, but if we try we get in trouble
070: // in some cases where the data is continually re-read after the dialog
071: // goes away (because the cell is being re-painted).
072: return false; // cell is not editable
073: }
074: (_data.get(row))[col] = newValue;
075: }
076:
077: return _creator.isColumnEditable(col, getValueAt(row, col));
078: }
079:
080: public Object getValueAt(int row, int col) {
081: if (RowNumberTableColumn.ROW_NUMBER_MODEL_INDEX == col) {
082: return Integer.valueOf(row + 1);
083: } else {
084: return _data.get(row)[col];
085: }
086: }
087:
088: public int getRowCount() {
089: return _data.size();
090: }
091:
092: public int getColumnCount() {
093: return _colDefs != null ? _colDefs.length : 0;
094: }
095:
096: public String getColumnName(int col) {
097: if (col == RowNumberTableColumn.ROW_NUMBER_MODEL_INDEX) {
098: return RowNumberTableColumn.ROW_NUMBER_HEADER;
099: } else {
100: return _colDefs != null ? _colDefs[col].getLabel() : super
101: .getColumnName(col);
102: }
103: }
104:
105: public Class<?> getColumnClass(int col) {
106: try {
107: // if no columns defined, return a generic class
108: // to avoid anything throwing an exception.
109: if (_colDefs == null) {
110: return Object.class;
111: }
112:
113: return Class.forName(_colDefs[col].getClassName());
114: } catch (Exception e) {
115: return null;
116: }
117: }
118:
119: void setHeadings(ColumnDisplayDefinition[] hdgs) {
120: _colDefs = hdgs;
121: }
122:
123: public void addRow(Object[] row) {
124: _data.add(row);
125: }
126:
127: void clear() {
128: _data.clear();
129: }
130:
131: public void allRowsAdded() {
132: fireTableStructureChanged();
133: }
134:
135: /**
136: * Let creator handle saving the data, if anything is to be done with it.
137: * If the creator succeeds in changing the underlying data,
138: * then update the JTable as well.
139: */
140: public void setValueAt(Object newValue, int row, int col) {
141: int[] colsToUpdate = _creator.changeUnderlyingValueAt(row, col,
142: newValue, getValueAt(row, col));
143:
144: for (int i = 0; i < colsToUpdate.length; i++) {
145: _data.get(row)[colsToUpdate[i]] = newValue;
146: }
147: }
148:
149: /**
150: * Delete a set of selected rows.
151: */
152: public void deleteRows(int[] rows) {
153: // The list of rows may be empty, in which case we just return.
154: if (rows.length == 0)
155: return;
156:
157: // We want to delete rows from the end of the table towards the beginning
158: // of the table. If we delete from the front to the back, that throws off
159: // the indexes of the rows after each delete and we would have to compensate
160: // for that.
161: // Example: if we want to delete rows 2 and 4 and do it in that
162: // order, then after deleteing row 2 the row that used to be row 4 is now
163: // actually row 3, so we would have to subtract 1 from the index to get the
164: // row to delete.
165: // On the other hand, if we delete row 4 first, then the indexes of all
166: // rows prior to that one have not been affected, so we can then delete
167: // row 2 without any complications.
168:
169: // sort the indexes into ascending order (because that is the
170: // only function easilly available from the Arrays class)
171: Arrays.sort(rows);
172:
173: // The indexes are in ascending order, but we want to delete in
174: // descending order (see previous comment), so run through the
175: // list backwards.
176: for (int i = rows.length - 1; i >= 0; i--) {
177: // delete the row from the table
178: if (rows[i] < _data.size()) {
179: _data.remove(rows[i]);
180: }
181: }
182:
183: // notify table that rows have changed
184: // The deleted rows may not be contiguous in the actual data model
185: // because the gui may be showing a version of the data sorted in
186: // some other order, so we cannot use fireRowsDeleted.
187: fireTableDataChanged();
188:
189: }
190: }
|