001/* AbstractTableModel.java --
002   Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.swing.table;
040
041import gnu.java.lang.CPStringBuilder;
042
043import java.io.Serializable;
044import java.util.EventListener;
045
046import javax.swing.event.EventListenerList;
047import javax.swing.event.TableModelEvent;
048import javax.swing.event.TableModelListener;
049
050/**
051 * A base class that can be used to create implementations of the
052 * {@link TableModel} interface.
053 *
054 * @author Andrew Selkirk
055 */
056public abstract class AbstractTableModel implements TableModel, Serializable
057{
058  static final long serialVersionUID = -5798593159423650347L;
059
060  /**
061   * Storage for the listeners registered with this model.
062   */
063  protected EventListenerList listenerList = new EventListenerList();
064
065  /**
066   * Creates a default instance.
067   */
068  public AbstractTableModel()
069  {
070    // no setup required here
071  }
072
073  /**
074   * Returns the name of the specified column.  This method generates default
075   * names in a sequence (starting with column 0):  A, B, C, ..., Z, AA, AB,
076   * AC, ..., AZ, BA, BB, BC, and so on.  Subclasses may override this method
077   * to allow column names to be specified on some other basis.
078   *
079   * @param columnIndex  the column index.
080   *
081   * @return The name of the column.
082   */
083  public String getColumnName(int columnIndex)
084  {
085    CPStringBuilder buffer = new CPStringBuilder();
086    while (columnIndex >= 0)
087      {
088        buffer.insert(0, (char) ('A' + columnIndex % 26));
089        columnIndex = columnIndex / 26 - 1;
090      }
091    return buffer.toString();
092  }
093
094  /**
095   * Return the index of the specified column, or <code>-1</code> if there is
096   * no column with the specified name.
097   *
098   * @param columnName  the name of the column (<code>null</code> not permitted).
099   *
100   * @return The index of the column, -1 if not found.
101   *
102   * @see #getColumnName(int)
103   * @throws NullPointerException if <code>columnName</code> is
104   *         <code>null</code>.
105   */
106  public int findColumn(String columnName)
107  {
108    int count = getColumnCount();
109
110    for (int index = 0; index < count; index++)
111      {
112        String name = getColumnName(index);
113
114        if (columnName.equals(name))
115          return index;
116    }
117
118    // Unable to locate.
119    return -1;
120  }
121
122  /**
123   * Returns the <code>Class</code> for all <code>Object</code> instances
124   * in the specified column.
125   *
126   * @param columnIndex the column index.
127   *
128   * @return The class.
129   */
130  public Class<?> getColumnClass(int columnIndex)
131  {
132    return Object.class;
133  }
134
135  /**
136   * Returns <code>true</code> if the specified cell is editable, and
137   * <code>false</code> if it is not.  This implementation returns
138   * <code>false</code> for all arguments, subclasses should override the
139   * method if necessary.
140   *
141   * @param rowIndex  the row index of the cell.
142   * @param columnIndex  the column index of the cell.
143   *
144   * @return <code>false</code>.
145   */
146  public boolean isCellEditable(int rowIndex, int columnIndex)
147  {
148    return false;
149  }
150
151  /**
152   * Sets the value of the given cell.  This implementation ignores all
153   * arguments and does nothing, subclasses should override the
154   * method if necessary.
155   *
156   * @param value  the new value (<code>null</code> permitted).
157   * @param rowIndex  the row index of the cell.
158   * @param columnIndex  the column index of the cell.
159   */
160  public void setValueAt(Object value, int rowIndex, int columnIndex)
161  {
162    // Do nothing...
163  }
164
165  /**
166   * Adds a listener to the table model.  The listener will receive notification
167   * of all changes to the table model.
168   *
169   * @param listener  the listener.
170   */
171  public void addTableModelListener(TableModelListener listener)
172  {
173    listenerList.add(TableModelListener.class, listener);
174  }
175
176  /**
177   * Removes a listener from the table model so that it will no longer receive
178   * notification of changes to the table model.
179   *
180   * @param listener  the listener to remove.
181   */
182  public void removeTableModelListener(TableModelListener listener)
183  {
184    listenerList.remove(TableModelListener.class, listener);
185  }
186
187  /**
188   * Returns an array containing the listeners that have been added to the
189   * table model.
190   *
191   * @return Array of {@link TableModelListener} objects.
192   *
193   * @since 1.4
194   */
195  public TableModelListener[] getTableModelListeners()
196  {
197    return (TableModelListener[])
198      listenerList.getListeners(TableModelListener.class);
199  }
200
201  /**
202   * Sends a {@link TableModelEvent} to all registered listeners to inform
203   * them that the table data has changed.
204   */
205  public void fireTableDataChanged()
206  {
207    fireTableChanged(new TableModelEvent(this, 0, Integer.MAX_VALUE));
208  }
209
210  /**
211   * Sends a {@link TableModelEvent} to all registered listeners to inform
212   * them that the table structure has changed.
213   */
214  public void fireTableStructureChanged()
215  {
216    fireTableChanged(new TableModelEvent(this, TableModelEvent.HEADER_ROW));
217  }
218
219  /**
220   * Sends a {@link TableModelEvent} to all registered listeners to inform
221   * them that some rows have been inserted into the model.
222   *
223   * @param firstRow  the index of the first row.
224   * @param lastRow  the index of the last row.
225   */
226  public void fireTableRowsInserted(int firstRow, int lastRow)
227  {
228    fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
229                                         TableModelEvent.ALL_COLUMNS,
230                                         TableModelEvent.INSERT));
231  }
232
233  /**
234   * Sends a {@link TableModelEvent} to all registered listeners to inform
235   * them that some rows have been updated.
236   *
237   * @param firstRow  the index of the first row.
238   * @param lastRow  the index of the last row.
239   */
240  public void fireTableRowsUpdated(int firstRow, int lastRow)
241  {
242    fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
243                                         TableModelEvent.ALL_COLUMNS,
244                                         TableModelEvent.UPDATE));
245  }
246
247  /**
248   * Sends a {@link TableModelEvent} to all registered listeners to inform
249   * them that some rows have been deleted from the model.
250   *
251   * @param firstRow  the index of the first row.
252   * @param lastRow  the index of the last row.
253   */
254  public void fireTableRowsDeleted(int firstRow, int lastRow)
255  {
256    fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
257                                         TableModelEvent.ALL_COLUMNS,
258                                         TableModelEvent.DELETE));
259  }
260
261  /**
262   * Sends a {@link TableModelEvent} to all registered listeners to inform
263   * them that a single cell has been updated.
264   *
265   * @param row  the row index.
266   * @param column  the column index.
267   */
268  public void fireTableCellUpdated(int row, int column)
269  {
270    fireTableChanged(new TableModelEvent(this, row, row, column));
271  }
272
273  /**
274   * Sends the specified event to all registered listeners.
275   *
276   * @param event  the event to send.
277   */
278  public void fireTableChanged(TableModelEvent event)
279  {
280    int index;
281    TableModelListener listener;
282    Object[] list = listenerList.getListenerList();
283
284    for (index = 0; index < list.length; index += 2)
285      {
286        listener = (TableModelListener) list [index + 1];
287        listener.tableChanged(event);
288      }
289  }
290
291  /**
292   * Returns an array of listeners of the given type that are registered with
293   * this model.
294   *
295   * @param listenerType  the listener class.
296   *
297   * @return An array of listeners (possibly empty).
298   */
299  public <T extends EventListener> T[] getListeners(Class<T> listenerType)
300  {
301    return listenerList.getListeners(listenerType);
302  }
303}