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 }