package util.swing; import java.util.Comparator; import util.ReverseOrderComparator; /** * A {@link javax.swing.table.TableModel} that models a list of records rather than a matrix of cells. * * <p>Usage of this TableModel is always recommendable when the data that is to be displayed consists of * a list of uniformly structured records and you want to display a selection of attributes for each record. * As the data management classes ({@link data.Catalog}, {@link data.Stock}, {@link data.DataBasket}) of the * "SalesPoint" framework match this scheme, there are concrete subclasses of this model for each of * those classes.</p> * * <p><code>util.swing.AbstractTableModel</code> will give one row in the table to each record of the model. * The record that is to be displayed in a certain row is determined by the {@link #getRecord} method which is * <i>abstract</i> and must be overridden in subclasses. Thus, subclasses have the opportunity to define what * type (class) of records they use and how they are derived from the actual data source in the background. * There's only one more method that subclasses will have to override: * {@link javax.swing.table.TableModel#getRowCount}.</p> * * <p>A {@link TableEntryDescriptor} will be used to determine how individual records are represented in one * row of the table model, i.e. how many columns there are and what is displayed in the cells as well as * formatting and editing issues.</p> * * @see JAbstractTable * * @author Steffen Zschaler * @version 2.0 28/07/1999 * @since v2.0 */ public abstract class AbstractTableModel extends javax.swing.table.AbstractTableModel { /** * The {@link TableEntryDescriptor} that is used to split records into columns. * * @serial */ private TableEntryDescriptor m_tedEntryDescriptor; /** * Create a new AbstractTableModel. * * @param ted the {@link TableEntryDescriptor} that is to be used to split records into columns. */ public AbstractTableModel(TableEntryDescriptor ted) { super(); m_tedEntryDescriptor = ted; } /** * Get the {@link TableEntryDescriptor} that is used to split records into columns. * * @override Never */ public TableEntryDescriptor getEntryDescriptor() { return m_tedEntryDescriptor; } /** * Get the number of columns in this {@link javax.swing.table.TableModel}. * * @return the number of columns in the associated {@link TableEntryDescriptor}. * * @override Never * * @see TableEntryDescriptor#getColumnCount */ public int getColumnCount() { return m_tedEntryDescriptor.getColumnCount(); } /** * Get the name of the given column in this {@link javax.swing.table.TableModel}. * * @param nIdx the column's index. Columns indices run from 0 to * {@link #getColumnCount getColumnCount() - 1}. * * @return the name of the column in the associated {@link TableEntryDescriptor}. * * @override Never * * @see TableEntryDescriptor#getColumnName */ public String getColumnName (int nIdx) { return m_tedEntryDescriptor.getColumnName (nIdx); } /** * Get the class of the given column in this {@link javax.swing.table.TableModel}. * * @param nIdx the column's index. Columns indices run from 0 to * {@link #getColumnCount getColumnCount() - 1}. * * @return the class of the column in the associated {@link TableEntryDescriptor}. * * @override Never * * @see TableEntryDescriptor#getColumnClass */ public Class getColumnClass (int nIdx) { return m_tedEntryDescriptor.getColumnClass (nIdx); } /** * Get the value of the given cell in this {@link javax.swing.table.TableModel}. * * <p>First determines the record associated to the row by calling {@link #getRecord}, then calls * {@link TableEntryDescriptor#getValueAt getValueAt()} in the associated TableEntryDescriptor.</p> * * @param row the row index for which to determine the value. This will be passed on to {@link #getRecord}. * Row indices run from 0 to {@link javax.swing.table.TableModel#getRowCount getRowCount() - 1}. * @param col the column's index. Columns indices run from 0 to * {@link #getColumnCount getColumnCount() - 1}. * * @return the value returned by {@link TableEntryDescriptor#getValueAt}. * * @override Never */ public Object getValueAt (int row, int col) { Object oRecord = getRecord (row); if (oRecord != null) { return m_tedEntryDescriptor.getValueAt (oRecord, col); } else { return null; } } /** * Check whether the given cell is editable in this {@link javax.swing.table.TableModel}. * * <p>First determines the record associated to the row by calling {@link #getRecord}, then calls * {@link TableEntryDescriptor#isElementEditable isElementEditable()} in the associated * TableEntryDescriptor.</p> * * @param row the row index for which to determine editability. This will be passed on to {@link #getRecord}. * Row indices run from 0 to {@link javax.swing.table.TableModel#getRowCount getRowCount() - 1}. * @param col the column's index. Columns indices run from 0 to * {@link #getColumnCount getColumnCount() - 1}. * * @return the value returned by {@link TableEntryDescriptor#isElementEditable}. * * @override Never */ public boolean isCellEditable (int row, int col) { Object oRecord = getRecord (row); if (oRecord != null) { return m_tedEntryDescriptor.isElementEditable (oRecord, col); } else { return false; } } /** * Set the value of the given cell in this {@link javax.swing.table.TableModel}. * * <p>First determines the record associated to the row by calling {@link #getRecord}, then calls * {@link TableEntryDescriptor#setValueAt setValueAt()} in the associated TableEntryDescriptor.</p> * * @param oValue the new value for the cell. This will be passed on to * {@link TableEntryDescriptor#setValueAt} as the <code>oValue</code> parameter. * @param row the row index for which to set the value. This will be passed on to {@link #getRecord}. * Row indices run from 0 to {@link javax.swing.table.TableModel#getRowCount getRowCount() - 1}. * @param col the column's index. Columns indices run from 0 to * {@link #getColumnCount getColumnCount() - 1}. * * @override Never */ public void setValueAt (Object oValue, int row, int col) { Object oRecord = getRecord (row); if (oRecord != null) { m_tedEntryDescriptor.setValueAt (oRecord, col, oValue); fireTableCellUpdated (row, col); } } /** * Reorders the table by the specified column if that's possible. * * @param nIdx the index of the column by which to sort * @param fAscending if false orders the records in descending order * * @see #reOrderBy * * @override Never * * @since v3.0 12/14/2000 */ public void orderByColumn (int nIdx, boolean fAscending) { if (m_tedEntryDescriptor.canSortByColumn (nIdx)) { Comparator cmp = m_tedEntryDescriptor.getColumnOrder (nIdx); if (! fAscending) { cmp = new ReverseOrderComparator (cmp); } reOrderBy (cmp); } } /** * Get the record associated to the given row. * * <p>Subclasses must indicate the class of the record in their documentation.</p> * * @param row the row index for which to return the record. Row indices run from 0 to * {@link javax.swing.table.TableModel#getRowCount getRowCount() - 1}. * * @return the record associated to the given row. May return <code>null</code>, instead of throwing an exception, * if the given index is without its bounds. * * @override Always You must override this method to define and incorporate your own type of record. * Subclasses should specify what class of record is returned. */ public abstract Object getRecord (int row); /** * Reorder the records displayed according to the specified comparator. * * @param cmp the comparator by which to order. * * @override Sometimes Override this method if you want sorting by column for your derived models. The * default implementation does nothing. * Subclasses should specify what class of record is maintained and whether the comparators must compare * whole records or just specific attributes. * * @since v3.0 12/14/2000 */ protected void reOrderBy (Comparator cmp) { } }