1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts2.components.table;
22
23 import java.awt.event.MouseAdapter;
24 import java.awt.event.MouseEvent;
25 import java.util.ArrayList;
26 import java.util.Collections;
27
28 import javax.swing.JTable;
29 import javax.swing.event.TableModelEvent;
30 import javax.swing.event.TableModelListener;
31 import javax.swing.table.TableModel;
32
33
34 /***
35 */
36 public class SortFilterModel extends AbstractFilterModel implements TableModelListener, SortableTableModel {
37
38 private static final long serialVersionUID = 2214225803442793597L;
39
40 private ArrayList rows = new ArrayList();
41
42 /***
43 * These are just here to implement the interface
44 */
45 private String _sortDirection = NONE;
46 private boolean dirty = true;
47 private int sortColumn = -1;
48
49
50 public SortFilterModel(TableModel tm) {
51 super(tm);
52 setModel(tm);
53 }
54
55
56 public boolean isCellEditable(int r, int c) {
57 if ((rows.size() > 0) && (r < rows.size())) {
58 return model.isCellEditable(((Row) rows.get(r)).index, c);
59 }
60
61 return false;
62 }
63
64 public void setModel(TableModel tm) {
65 super.setModel(tm);
66 rows.ensureCapacity(model.getRowCount());
67 model.addTableModelListener(this);
68 sortColumn = -1;
69 dirty = true;
70 refresh();
71 }
72
73 public int getSortedColumnNumber() {
74 return sortColumn;
75 }
76
77 public String getSortedDirection(int columnNumber) {
78 if (getSortedColumnNumber() < 0) {
79 return NONE;
80 }
81
82 return _sortDirection;
83 }
84
85 public void setValueAt(Object aValue, int r, int c) {
86 if ((rows.size() > 0) && (r < rows.size())) {
87 model.setValueAt(aValue, ((Row) rows.get(r)).index, c);
88 }
89 }
90
91
92
93
94 public Object getValueAt(int r, int c) {
95 if ((rows.size() > 0) && (r < rows.size())) {
96 return model.getValueAt(((Row) rows.get(r)).index, c);
97 }
98
99 return null;
100 }
101
102 public void addMouseListener(final JTable table) {
103 table.getTableHeader().addMouseListener(new MouseAdapter() {
104 public void mouseClicked(MouseEvent event) {
105
106 if (event.getClickCount() < 2) {
107 return;
108 }
109
110
111 int tableColumn = table.columnAtPoint(event.getPoint());
112
113
114 int modelColumn = table.convertColumnIndexToModel(tableColumn);
115 sort(modelColumn);
116 }
117 });
118 }
119
120 public void removeRow(int rowNum) throws ArrayIndexOutOfBoundsException, IllegalStateException {
121 int mappedRow = ((Row) rows.get(rowNum)).index;
122 super.removeRow(mappedRow);
123 }
124
125 public void sort(int columnNumber, String direction) {
126 _sortDirection = ASC;
127 dirty = true;
128 sort(columnNumber);
129
130 if (DESC.equals(direction)) {
131 sort(columnNumber);
132 _sortDirection = DESC;
133 }
134 }
135
136 /***
137 * Implements the TableModelListener interface to receive
138 * notifications of * changes to the table model. SortFilterModel needs
139 * to receive events for adding and removing rows.
140 */
141 public void tableChanged(TableModelEvent e) {
142 dirty = true;
143 refresh();
144 fireTableChanged(e);
145 }
146
147 protected void refresh() {
148 rows.clear();
149
150 for (int i = 0; i < model.getRowCount(); i++) {
151 rows.add(new Row(i));
152 }
153
154 if (dirty && (sortColumn > -1)) {
155 sort(sortColumn);
156 }
157 }
158
159 protected void sort(int c) {
160 boolean sorted = (sortColumn == c);
161 sortColumn = c;
162
163 if (dirty || !sorted) {
164 Collections.sort(rows);
165 dirty = false;
166 } else {
167 Collections.reverse(rows);
168 }
169
170 fireTableDataChanged();
171 }
172
173
174
175
176
177
178 private class Row implements Comparable {
179 public int index;
180
181 public Row(int index) {
182 this.index = index;
183 }
184
185 public int compareTo(Object other) {
186 Row otherRow = (Row) other;
187 Object a = model.getValueAt(index, sortColumn);
188 Object b = model.getValueAt(otherRow.index, sortColumn);
189
190 boolean areTheyCompareable = (a instanceof Comparable && b instanceof Comparable && (a.getClass() == b.getClass()));
191
192 if (areTheyCompareable) {
193 return ((Comparable) a).compareTo((Comparable) b);
194 } else {
195 return a.toString().compareTo(b.toString());
196 }
197 }
198 }
199 }