001 package util.swing; 002 003 import java.util.Comparator; 004 005 import data.Catalog; 006 import data.swing.CatalogTableModel; 007 008 import util.ReverseOrderComparator; 009 010 /** 011 * A {@link javax.swing.table.TableModel} that models a list of records rather than a matrix of cells. 012 * 013 * <p>Usage of this TableModel is always recommendable when the data that is to be displayed consists of 014 * a list of uniformly structured records and you want to display a selection of attributes for each record. 015 * As the data management classes ({@link data.Catalog}, {@link data.Stock}, {@link data.DataBasket}) of the 016 * "SalesPoint" framework match this scheme, there are concrete subclasses of this model for each of 017 * those classes.</p> 018 * 019 * <p><code>util.swing.AbstractTableModel</code> will give one row in the table to each record of the model. 020 * The record that is to be displayed in a certain row is determined by the {@link #getRecord} method which is 021 * <i>abstract</i> and must be overridden in subclasses. Thus, subclasses have the opportunity to define what 022 * type (class) of records they use and how they are derived from the actual data source in the background. 023 * There's only one more method that subclasses will have to override: 024 * {@link javax.swing.table.TableModel#getRowCount}.</p> 025 * 026 * <p>A {@link TableEntryDescriptor} will be used to determine how individual records are represented in one 027 * row of the table model, i.e. how many columns there are and what is displayed in the cells as well as 028 * formatting and editing issues.</p> 029 * 030 * @see JAbstractTable 031 * 032 * @author Steffen Zschaler 033 * @version 2.0 28/07/1999 034 * @since v2.0 035 */ 036 public abstract class AbstractTableModel extends javax.swing.table.AbstractTableModel { 037 038 /** 039 * The {@link TableEntryDescriptor} that is used to split records into columns. 040 * 041 * @serial 042 */ 043 private TableEntryDescriptor m_tedEntryDescriptor; 044 045 /** 046 * Set the table's data. 047 * @param data the new data 048 * @throws Exception 049 */ 050 public abstract void setData(Object data); 051 052 /** 053 * Create a new AbstractTableModel. 054 * 055 * @param ted the {@link TableEntryDescriptor} that is to be used to split records into columns. 056 */ 057 public AbstractTableModel(TableEntryDescriptor ted) { 058 super(); 059 060 m_tedEntryDescriptor = ted; 061 } 062 063 /** 064 * Get the {@link TableEntryDescriptor} that is used to split records into columns. 065 * 066 * @override Never 067 */ 068 public TableEntryDescriptor getEntryDescriptor() { 069 return m_tedEntryDescriptor; 070 } 071 072 /** 073 * Get the number of columns in this {@link javax.swing.table.TableModel}. 074 * 075 * @return the number of columns in the associated {@link TableEntryDescriptor}. 076 * 077 * @override Never 078 * 079 * @see TableEntryDescriptor#getColumnCount 080 */ 081 public int getColumnCount() { 082 return m_tedEntryDescriptor.getColumnCount(); 083 } 084 085 /** 086 * Get the name of the given column in this {@link javax.swing.table.TableModel}. 087 * 088 * @param nIdx the column's index. Columns indices run from 0 to 089 * {@link #getColumnCount getColumnCount() - 1}. 090 * 091 * @return the name of the column in the associated {@link TableEntryDescriptor}. 092 * 093 * @override Never 094 * 095 * @see TableEntryDescriptor#getColumnName 096 */ 097 public String getColumnName(int nIdx) { 098 return m_tedEntryDescriptor.getColumnName(nIdx); 099 } 100 101 /** 102 * Get the class of the given column in this {@link javax.swing.table.TableModel}. 103 * 104 * @param nIdx the column's index. Columns indices run from 0 to 105 * {@link #getColumnCount getColumnCount() - 1}. 106 * 107 * @return the class of the column in the associated {@link TableEntryDescriptor}. 108 * 109 * @override Never 110 * 111 * @see TableEntryDescriptor#getColumnClass 112 */ 113 public Class getColumnClass(int nIdx) { 114 return m_tedEntryDescriptor.getColumnClass(nIdx); 115 } 116 117 /** 118 * Get the value of the given cell in this {@link javax.swing.table.TableModel}. 119 * 120 * <p>First determines the record associated to the row by calling {@link #getRecord}, then calls 121 * {@link TableEntryDescriptor#getValueAt getValueAt()} in the associated TableEntryDescriptor.</p> 122 * 123 * @param row the row index for which to determine the value. This will be passed on to {@link #getRecord}. 124 * Row indices run from 0 to {@link javax.swing.table.TableModel#getRowCount getRowCount() - 1}. 125 * @param col the column's index. Columns indices run from 0 to 126 * {@link #getColumnCount getColumnCount() - 1}. 127 * 128 * @return the value returned by {@link TableEntryDescriptor#getValueAt}. 129 * 130 * @override Never 131 */ 132 public Object getValueAt(int row, int col) { 133 Object oRecord = getRecord(row); 134 if (oRecord != null) { 135 return m_tedEntryDescriptor.getValueAt(oRecord, col); 136 } else { 137 return null; 138 } 139 } 140 141 /** 142 * Check whether the given cell is editable in this {@link javax.swing.table.TableModel}. 143 * 144 * <p>First determines the record associated to the row by calling {@link #getRecord}, then calls 145 * {@link TableEntryDescriptor#isElementEditable isElementEditable()} in the associated 146 * TableEntryDescriptor.</p> 147 * 148 * @param row the row index for which to determine editability. This will be passed on to {@link #getRecord}. 149 * Row indices run from 0 to {@link javax.swing.table.TableModel#getRowCount getRowCount() - 1}. 150 * @param col the column's index. Columns indices run from 0 to 151 * {@link #getColumnCount getColumnCount() - 1}. 152 * 153 * @return the value returned by {@link TableEntryDescriptor#isElementEditable}. 154 * 155 * @override Never 156 */ 157 public boolean isCellEditable(int row, int col) { 158 Object oRecord = getRecord(row); 159 if (oRecord != null) { 160 return m_tedEntryDescriptor.isElementEditable(oRecord, col); 161 } else { 162 return false; 163 } 164 } 165 166 /** 167 * Set the value of the given cell in this {@link javax.swing.table.TableModel}. 168 * 169 * <p>First determines the record associated to the row by calling {@link #getRecord}, then calls 170 * {@link TableEntryDescriptor#setValueAt setValueAt()} in the associated TableEntryDescriptor.</p> 171 * 172 * @param oValue the new value for the cell. This will be passed on to 173 * {@link TableEntryDescriptor#setValueAt} as the <code>oValue</code> parameter. 174 * @param row the row index for which to set the value. This will be passed on to {@link #getRecord}. 175 * Row indices run from 0 to {@link javax.swing.table.TableModel#getRowCount getRowCount() - 1}. 176 * @param col the column's index. Columns indices run from 0 to 177 * {@link #getColumnCount getColumnCount() - 1}. 178 * 179 * @override Never 180 */ 181 public void setValueAt(Object oValue, int row, int col) { 182 Object oRecord = getRecord(row); 183 if (oRecord != null) { 184 m_tedEntryDescriptor.setValueAt(oRecord, col, oValue); 185 186 fireTableCellUpdated(row, col); 187 } 188 } 189 190 /** 191 * Reorders the table by the specified column if that's possible. 192 * 193 * @param nIdx the index of the column by which to sort 194 * @param fAscending if false orders the records in descending order 195 * 196 * @see #reOrderBy 197 * 198 * @override Never 199 * 200 * @since v3.0 12/14/2000 201 */ 202 public void orderByColumn(int nIdx, boolean fAscending) { 203 if (m_tedEntryDescriptor.canSortByColumn(nIdx)) { 204 Comparator cmp = m_tedEntryDescriptor.getColumnOrder(nIdx); 205 206 if (!fAscending) { 207 cmp = new ReverseOrderComparator(cmp); 208 } 209 210 reOrderBy(cmp); 211 } 212 } 213 214 /** 215 * Get the record associated to the given row. 216 * 217 * <p>Subclasses must indicate the class of the record in their documentation.</p> 218 * 219 * @param row the row index for which to return the record. Row indices run from 0 to 220 * {@link javax.swing.table.TableModel#getRowCount getRowCount() - 1}. 221 * 222 * @return the record associated to the given row. May return <code>null</code>, instead of throwing an exception, 223 * if the given index is without its bounds. 224 * 225 * @override Always You must override this method to define and incorporate your own type of record. 226 * Subclasses should specify what class of record is returned. 227 */ 228 public abstract Object getRecord(int row); 229 230 /** 231 * Reorder the records displayed according to the specified comparator. 232 * 233 * @param cmp the comparator by which to order. 234 * 235 * @override Sometimes Override this method if you want sorting by column for your derived models. The 236 * default implementation does nothing. 237 * Subclasses should specify what class of record is maintained and whether the comparators must compare 238 * whole records or just specific attributes. 239 * 240 * @since v3.0 12/14/2000 241 */ 242 protected void reOrderBy(Comparator cmp) { 243 } 244 }