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