1 /***
2 * JReportTable.java
3 *
4 * This file is part of the creme library.
5 * The creme library intends to ease the development effort of large
6 * applications by providing easy to use support classes.
7 *
8 * Copyright (C) 2003 Denis Bregeon
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * contact information: dbregeon@sourceforge.net
25 */
26 package org.jcreme.swing.reporting;
27
28 import java.util.HashSet;
29
30 import javax.swing.ImageIcon;
31 import javax.swing.table.JTableHeader;
32 import javax.swing.table.TableColumn;
33 import javax.swing.table.TableColumnModel;
34 import javax.swing.table.TableModel;
35
36 import org.jcreme.enumerations.ComparatorType;
37 import org.jcreme.enumerations.SortOrder;
38 import org.jcreme.reporting.Report;
39 import org.jcreme.swing.table.JColoredTable;
40 import org.jcreme.swing.table.SortableColumnHeaderMouseListener;
41 import org.jcreme.swing.table.SortableColumnTableHeaderRenderer;
42 import org.jcreme.swing.table.SortableTableColumn;
43 import org.jcreme.swing.table.TableColumnOrderEvent;
44 import org.jcreme.swing.table.TableColumnOrderListener;
45 import org.jcreme.swing.table.columnmodel.EditableTableColumnModel;
46
47 /***
48 * This class provides all the defaults to easily integrate reports. It enables
49 * to display a sortable JTable from a report without efforts.
50 *
51 * @author $Author: dbregeon $
52 * @version $Revision: 1.1 $
53 */
54 public class JReportTable extends JColoredTable {
55 /***
56 * The icon displayed in the column header when sort is ASCENDING.
57 */
58 public static final ImageIcon ARROW_UP = new ImageIcon(JReportTable.class
59 .getClassLoader().getResource("images/uparrow.gif"));
60
61 /***
62 * The icon displayed in the column header when sort is DESCENDING.
63 */
64 public static final ImageIcon ARROW_DOWN = new ImageIcon(JReportTable.class
65 .getClassLoader().getResource("images/downarrow.gif"));
66
67 /***
68 * The underlying report for this table.
69 */
70 private Report report = null;
71
72 /***
73 * The columns currently in use in the sort.
74 */
75 private final HashSet sortedColumns = new HashSet();
76
77 /***
78 * The listener for the SortableTableColumns to react to changes in a column
79 * order.
80 */
81 private final TableColumnOrderListener tableColumnOrderListener = new TableColumnOrderListener() {
82 public void tableColumnOrderChanged(TableColumnOrderEvent e) {
83 orderChanged((SortableTableColumn) e.getSource());
84 sort();
85 }
86 };
87
88 /***
89 * The listener to detect clicks on the JTableHeader to apply sort on the
90 * clicked column.
91 */
92 private final SortableColumnHeaderMouseListener headerColumnListener = new SortableColumnHeaderMouseListener();
93
94 /***
95 * This method enables to create the default TableModel for this Table.
96 *
97 * @return either the superclass result for createDefaultDataModel or a
98 * ReportTableModel instance if report is set.
99 */
100 protected TableModel createDefaultDataModel() {
101 TableModel result = null;
102 if (this.report != null) {
103 result = new ReportTableModel(this.report);
104 } else {
105 return super.createDefaultDataModel();
106 }
107 return result;
108 }
109
110 /***
111 * This method enabled to create the default TableColumnModel for this
112 * Table.
113 *
114 * @return either the superclass result for createDefaultColumnModel or an
115 * EditableTableColumnModel instance if report is set.
116 */
117 protected TableColumnModel createDefaultColumnModel() {
118 return new EditableTableColumnModel();
119 }
120
121 /***
122 * This method enables to set the ColumnModel. If the new model contains
123 * SortableTableColumn, listeners and renderers are set.
124 *
125 * @param model
126 * the new column model.
127 */
128 public void setColumnModel(TableColumnModel model) {
129 TableColumnModel cm = getColumnModel();
130 TableColumn current = null;
131 int count = 0;
132 while ((cm != null) && (count < cm.getColumnCount())) {
133 current = cm.getColumn(count);
134 if (current instanceof SortableTableColumn) {
135 ((SortableTableColumn) current)
136 .removeTableColumnOrderListener(this.tableColumnOrderListener);
137 count++;
138 }
139 }
140 super.setColumnModel(model);
141 cm = getColumnModel();
142 count = 0;
143 while ((cm != null) && (count < cm.getColumnCount())) {
144 current = cm.getColumn(count);
145 if (current instanceof SortableTableColumn) {
146 prepareColumn((SortableTableColumn) current);
147 orderChanged((SortableTableColumn) current);
148 }
149 count++;
150 }
151 sort();
152 }
153
154 /***
155 * This method enables to set the JTableHeader. Listeners are added to the
156 * new header.
157 *
158 * @param header
159 * the new JTableHeader.
160 */
161 public void setTableHeader(JTableHeader header) {
162 if (getTableHeader() != null) {
163 getTableHeader().removeMouseListener(this.headerColumnListener);
164 }
165 super.setTableHeader(header);
166 if (getTableHeader() != null) {
167 getTableHeader().addMouseListener(this.headerColumnListener);
168 }
169 }
170
171 /***
172 * This method creates the columns and adds them to the TableColumnModel,
173 * based on the TableModel. This method creates SortableTableColumns
174 * whenever at least one ComparatorType is associated to the column's class.
175 */
176 public void createDefaultColumnsFromModel() {
177 TableModel m = getModel();
178 if (m != null) {
179
180 TableColumnModel cm = getColumnModel();
181 while (cm.getColumnCount() > 0) {
182 if (cm.getColumn(0) instanceof SortableTableColumn) {
183 ((SortableTableColumn) cm.getColumn(0))
184 .removeTableColumnOrderListener(this.tableColumnOrderListener);
185 }
186 cm.removeColumn(cm.getColumn(0));
187 }
188
189
190 TableColumn newColumn = null;
191 SortableTableColumn newSortableColumn = null;
192 ComparatorType[] comparators = null;
193 Class columnClass = null;
194 String columnName = null;
195 for (int i = 0; i < m.getColumnCount(); i++) {
196 columnClass = m.getColumnClass(i);
197 columnName = m.getColumnName(i);
198 comparators = ComparatorType.getComparatorTypes(columnClass);
199 if ((comparators != null) && (comparators.length > 0)) {
200 newSortableColumn = new SortableTableColumn(i);
201 prepareColumn(newSortableColumn);
202 newSortableColumn
203 .setComparator((Comparable.class.isAssignableFrom(m
204 .getColumnClass(i))) ? ComparatorType.DEFAULT
205 : comparators[0]);
206 newSortableColumn.setColumnClass(columnClass);
207 newColumn = newSortableColumn;
208 } else {
209 newColumn = new TableColumn(i);
210 }
211 newColumn.setIdentifier(columnName);
212 newColumn.setHeaderValue(columnName);
213 newColumn.setResizable(true);
214 addColumn(newColumn);
215 }
216 }
217 }
218
219 /***
220 * Creates a default JTableHeader. This method acts the same way as the
221 * super class' except that listeners are added to the new Header.
222 *
223 * @return JTableHeader the header created for this table.
224 */
225 protected JTableHeader createDefaultTableHeader() {
226 if (super.getTableHeader() != null) {
227 super.getTableHeader().removeMouseListener(
228 this.headerColumnListener);
229 }
230 JTableHeader header = super.createDefaultTableHeader();
231 header.addMouseListener(this.headerColumnListener);
232 return header;
233 }
234
235 /***
236 * This method enables to set the report that will be presented in this
237 * Table.
238 *
239 * @param r
240 * the Report to present.
241 */
242 public void setReport(Report r) {
243 this.report = r;
244 getTableHeader().removeMouseListener(this.headerColumnListener);
245 setModel(createDefaultDataModel());
246 getTableHeader().addMouseListener(this.headerColumnListener);
247 sort();
248 }
249
250 /***
251 * This method enables to access the Report presented in this Table.
252 *
253 * @return the report presented.
254 */
255 public Report getReport() {
256 return this.report;
257 }
258
259 /***
260 * This is a convenience method to apply the sort to the TableModel, from
261 * the sortable columns.
262 */
263 protected void sort() {
264 TableModel model = getModel();
265 if (model instanceof ReportTableModel) {
266 ((ReportTableModel) model)
267 .sort((SortableTableColumn[]) this.sortedColumns
268 .toArray(new SortableTableColumn[0]));
269 }
270 }
271
272 /***
273 * This is a convenience method to handle column order changes.
274 *
275 * @param column
276 * the column for which order was changed.
277 */
278 protected void orderChanged(SortableTableColumn column) {
279 if (column.getOrder() != SortOrder.NONE) {
280 this.sortedColumns.add(column);
281 } else {
282 this.sortedColumns.remove(column);
283 }
284 }
285
286 /***
287 * This is a convenience method that installs listeners and header renderer
288 * on SortableTableColumns.
289 *
290 * @param column
291 * the column on which to install listeners and renderer.
292 */
293 protected void prepareColumn(SortableTableColumn column) {
294 column.setHeaderRenderer(new SortableColumnTableHeaderRenderer(column,
295 ARROW_DOWN, ARROW_UP));
296 column.addTableColumnOrderListener(this.tableColumnOrderListener);
297 }
298 }