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