1. /*
  2. * @(#)AbstractTableModel.java 1.41 04/05/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.table;
  8. import javax.swing.*;
  9. import javax.swing.event.*;
  10. import java.io.Serializable;
  11. import java.util.EventListener;
  12. /**
  13. * This abstract class provides default implementations for most of
  14. * the methods in the <code>TableModel</code> interface. It takes care of
  15. * the management of listeners and provides some conveniences for generating
  16. * <code>TableModelEvents</code> and dispatching them to the listeners.
  17. * To create a concrete <code>TableModel</code> as a subclass of
  18. * <code>AbstractTableModel</code> you need only provide implementations
  19. * for the following three methods:
  20. *
  21. * <pre>
  22. * public int getRowCount();
  23. * public int getColumnCount();
  24. * public Object getValueAt(int row, int column);
  25. * </pre>
  26. * <p>
  27. * <strong>Warning:</strong>
  28. * Serialized objects of this class will not be compatible with
  29. * future Swing releases. The current serialization support is
  30. * appropriate for short term storage or RMI between applications running
  31. * the same version of Swing. As of 1.4, support for long term storage
  32. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  33. * has been added to the <code>java.beans</code> package.
  34. * Please see {@link java.beans.XMLEncoder}.
  35. *
  36. * @version 1.41 05/05/04
  37. * @author Alan Chung
  38. * @author Philip Milne
  39. */
  40. public abstract class AbstractTableModel implements TableModel, Serializable
  41. {
  42. //
  43. // Instance Variables
  44. //
  45. /** List of listeners */
  46. protected EventListenerList listenerList = new EventListenerList();
  47. //
  48. // Default Implementation of the Interface
  49. //
  50. /**
  51. * Returns a default name for the column using spreadsheet conventions:
  52. * A, B, C, ... Z, AA, AB, etc. If <code>column</code> cannot be found,
  53. * returns an empty string.
  54. *
  55. * @param column the column being queried
  56. * @return a string containing the default name of <code>column</code>
  57. */
  58. public String getColumnName(int column) {
  59. String result = "";
  60. for (; column >= 0; column = column / 26 - 1) {
  61. result = (char)((char)(column%26)+'A') + result;
  62. }
  63. return result;
  64. }
  65. /**
  66. * Returns a column given its name.
  67. * Implementation is naive so this should be overridden if
  68. * this method is to be called often. This method is not
  69. * in the <code>TableModel</code> interface and is not used by the
  70. * <code>JTable</code>.
  71. *
  72. * @param columnName string containing name of column to be located
  73. * @return the column with <code>columnName</code>, or -1 if not found
  74. */
  75. public int findColumn(String columnName) {
  76. for (int i = 0; i < getColumnCount(); i++) {
  77. if (columnName.equals(getColumnName(i))) {
  78. return i;
  79. }
  80. }
  81. return -1;
  82. }
  83. /**
  84. * Returns <code>Object.class</code> regardless of <code>columnIndex</code>.
  85. *
  86. * @param columnIndex the column being queried
  87. * @return the Object.class
  88. */
  89. public Class<?> getColumnClass(int columnIndex) {
  90. return Object.class;
  91. }
  92. /**
  93. * Returns false. This is the default implementation for all cells.
  94. *
  95. * @param rowIndex the row being queried
  96. * @param columnIndex the column being queried
  97. * @return false
  98. */
  99. public boolean isCellEditable(int rowIndex, int columnIndex) {
  100. return false;
  101. }
  102. /**
  103. * This empty implementation is provided so users don't have to implement
  104. * this method if their data model is not editable.
  105. *
  106. * @param aValue value to assign to cell
  107. * @param rowIndex row of cell
  108. * @param columnIndex column of cell
  109. */
  110. public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
  111. }
  112. //
  113. // Managing Listeners
  114. //
  115. /**
  116. * Adds a listener to the list that's notified each time a change
  117. * to the data model occurs.
  118. *
  119. * @param l the TableModelListener
  120. */
  121. public void addTableModelListener(TableModelListener l) {
  122. listenerList.add(TableModelListener.class, l);
  123. }
  124. /**
  125. * Removes a listener from the list that's notified each time a
  126. * change to the data model occurs.
  127. *
  128. * @param l the TableModelListener
  129. */
  130. public void removeTableModelListener(TableModelListener l) {
  131. listenerList.remove(TableModelListener.class, l);
  132. }
  133. /**
  134. * Returns an array of all the table model listeners
  135. * registered on this model.
  136. *
  137. * @return all of this model's <code>TableModelListener</code>s
  138. * or an empty
  139. * array if no table model listeners are currently registered
  140. *
  141. * @see #addTableModelListener
  142. * @see #removeTableModelListener
  143. *
  144. * @since 1.4
  145. */
  146. public TableModelListener[] getTableModelListeners() {
  147. return (TableModelListener[])listenerList.getListeners(
  148. TableModelListener.class);
  149. }
  150. //
  151. // Fire methods
  152. //
  153. /**
  154. * Notifies all listeners that all cell values in the table's
  155. * rows may have changed. The number of rows may also have changed
  156. * and the <code>JTable</code> should redraw the
  157. * table from scratch. The structure of the table (as in the order of the
  158. * columns) is assumed to be the same.
  159. *
  160. * @see TableModelEvent
  161. * @see EventListenerList
  162. * @see javax.swing.JTable#tableChanged(TableModelEvent)
  163. */
  164. public void fireTableDataChanged() {
  165. fireTableChanged(new TableModelEvent(this));
  166. }
  167. /**
  168. * Notifies all listeners that the table's structure has changed.
  169. * The number of columns in the table, and the names and types of
  170. * the new columns may be different from the previous state.
  171. * If the <code>JTable</code> receives this event and its
  172. * <code>autoCreateColumnsFromModel</code>
  173. * flag is set it discards any table columns that it had and reallocates
  174. * default columns in the order they appear in the model. This is the
  175. * same as calling <code>setModel(TableModel)</code> on the
  176. * <code>JTable</code>.
  177. *
  178. * @see TableModelEvent
  179. * @see EventListenerList
  180. */
  181. public void fireTableStructureChanged() {
  182. fireTableChanged(new TableModelEvent(this, TableModelEvent.HEADER_ROW));
  183. }
  184. /**
  185. * Notifies all listeners that rows in the range
  186. * <code>[firstRow, lastRow]</code>, inclusive, have been inserted.
  187. *
  188. * @param firstRow the first row
  189. * @param lastRow the last row
  190. *
  191. * @see TableModelEvent
  192. * @see EventListenerList
  193. *
  194. */
  195. public void fireTableRowsInserted(int firstRow, int lastRow) {
  196. fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
  197. TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  198. }
  199. /**
  200. * Notifies all listeners that rows in the range
  201. * <code>[firstRow, lastRow]</code>, inclusive, have been updated.
  202. *
  203. * @param firstRow the first row
  204. * @param lastRow the last row
  205. *
  206. * @see TableModelEvent
  207. * @see EventListenerList
  208. */
  209. public void fireTableRowsUpdated(int firstRow, int lastRow) {
  210. fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
  211. TableModelEvent.ALL_COLUMNS, TableModelEvent.UPDATE));
  212. }
  213. /**
  214. * Notifies all listeners that rows in the range
  215. * <code>[firstRow, lastRow]</code>, inclusive, have been deleted.
  216. *
  217. * @param firstRow the first row
  218. * @param lastRow the last row
  219. *
  220. * @see TableModelEvent
  221. * @see EventListenerList
  222. */
  223. public void fireTableRowsDeleted(int firstRow, int lastRow) {
  224. fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
  225. TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE));
  226. }
  227. /**
  228. * Notifies all listeners that the value of the cell at
  229. * <code>[row, column]</code> has been updated.
  230. *
  231. * @param row row of cell which has been updated
  232. * @param column column of cell which has been updated
  233. * @see TableModelEvent
  234. * @see EventListenerList
  235. */
  236. public void fireTableCellUpdated(int row, int column) {
  237. fireTableChanged(new TableModelEvent(this, row, row, column));
  238. }
  239. /**
  240. * Forwards the given notification event to all
  241. * <code>TableModelListeners</code> that registered
  242. * themselves as listeners for this table model.
  243. *
  244. * @param e the event to be forwarded
  245. *
  246. * @see #addTableModelListener
  247. * @see TableModelEvent
  248. * @see EventListenerList
  249. */
  250. public void fireTableChanged(TableModelEvent e) {
  251. // Guaranteed to return a non-null array
  252. Object[] listeners = listenerList.getListenerList();
  253. // Process the listeners last to first, notifying
  254. // those that are interested in this event
  255. for (int i = listeners.length-2; i>=0; i-=2) {
  256. if (listeners[i]==TableModelListener.class) {
  257. ((TableModelListener)listeners[i+1]).tableChanged(e);
  258. }
  259. }
  260. }
  261. /**
  262. * Returns an array of all the objects currently registered
  263. * as <code><em>Foo</em>Listener</code>s
  264. * upon this <code>AbstractTableModel</code>.
  265. * <code><em>Foo</em>Listener</code>s are registered using the
  266. * <code>add<em>Foo</em>Listener</code> method.
  267. *
  268. * <p>
  269. *
  270. * You can specify the <code>listenerType</code> argument
  271. * with a class literal,
  272. * such as
  273. * <code><em>Foo</em>Listener.class</code>.
  274. * For example, you can query a
  275. * model <code>m</code>
  276. * for its table model listeners with the following code:
  277. *
  278. * <pre>TableModelListener[] tmls = (TableModelListener[])(m.getListeners(TableModelListener.class));</pre>
  279. *
  280. * If no such listeners exist, this method returns an empty array.
  281. *
  282. * @param listenerType the type of listeners requested; this parameter
  283. * should specify an interface that descends from
  284. * <code>java.util.EventListener</code>
  285. * @return an array of all objects registered as
  286. * <code><em>Foo</em>Listener</code>s on this component,
  287. * or an empty array if no such
  288. * listeners have been added
  289. * @exception ClassCastException if <code>listenerType</code>
  290. * doesn't specify a class or interface that implements
  291. * <code>java.util.EventListener</code>
  292. *
  293. * @see #getTableModelListeners
  294. *
  295. * @since 1.3
  296. */
  297. public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
  298. return listenerList.getListeners(listenerType);
  299. }
  300. } // End of class AbstractTableModel