1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.cosylab.gui.components.table;
21
22 import com.cosylab.logging.DebugLogger;
23
24 import com.cosylab.util.ObjectList;
25
26 import java.util.LinkedList;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29
30 import javax.swing.SwingUtilities;
31 import javax.swing.event.TableModelEvent;
32 import javax.swing.event.TableModelListener;
33 import javax.swing.table.TableModel;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class QueueTableModelInterceptor implements TableModel,
56 TableModelListener, Runnable
57 {
58 private final TableModel delegate;
59 private ObjectList listeners = new ObjectList(TableModelListener.class);
60 private final LinkedList<TableModelEvent> queue = new LinkedList<TableModelEvent>();
61 private final Logger logger = DebugLogger.getLogger("QTMI", Level.OFF);
62 private Interceptor updater;
63 private int relaxationTime=1000;
64 private boolean destroyed=false;
65
66 class Interceptor extends Thread
67 {
68 long last = System.currentTimeMillis();
69 boolean update = false;
70
71 public Interceptor() {
72 super();
73 }
74
75
76
77 public synchronized void run()
78 {
79 while (!destroyed) {
80 long t = System.currentTimeMillis();
81
82 if (update) {
83 if (t - last > relaxationTime || t-last + 1 <= 0) {
84 SwingUtilities.invokeLater(QueueTableModelInterceptor.this);
85 last = t;
86 update = false;
87 } else {
88 try {
89 wait(t - last + 1);
90 } catch (Exception e) {
91 e.printStackTrace();
92 }
93 }
94 } else {
95 try {
96 wait(0);
97 } catch (Exception e) {
98 e.printStackTrace();
99 }
100 }
101 }
102 }
103
104
105
106
107 public synchronized void update()
108 {
109 update = true;
110 notifyAll();
111 }
112 }
113
114
115
116
117
118
119 public QueueTableModelInterceptor(TableModel delegate)
120 {
121
122 this.delegate = delegate;
123
124 delegate.addTableModelListener(this);
125
126 updater = new Interceptor();
127 updater.start();
128 }
129
130
131
132
133 public int getColumnCount()
134 {
135 return delegate.getColumnCount();
136 }
137
138
139
140
141 public int getRowCount()
142 {
143 return delegate.getRowCount();
144 }
145
146
147
148
149 public boolean isCellEditable(int rowIndex, int columnIndex)
150 {
151 return delegate.isCellEditable(rowIndex, columnIndex);
152 }
153
154
155
156
157 public Class<?> getColumnClass(int columnIndex)
158 {
159 return delegate.getColumnClass(columnIndex);
160 }
161
162
163
164
165 public Object getValueAt(int rowIndex, int columnIndex)
166 {
167 return delegate.getValueAt(rowIndex, columnIndex);
168 }
169
170
171
172
173 public void setValueAt(Object aValue, int rowIndex, int columnIndex)
174 {
175 delegate.setValueAt(aValue, rowIndex, columnIndex);
176 }
177
178
179
180
181 public String getColumnName(int columnIndex)
182 {
183 return delegate.getColumnName(columnIndex);
184 }
185
186
187
188
189 public void addTableModelListener(TableModelListener l)
190 {
191 listeners.add(l);
192 }
193
194
195
196
197 public void removeTableModelListener(TableModelListener l)
198 {
199 listeners.remove(l);
200 }
201
202
203
204
205
206
207 public TableModel getDelegate()
208 {
209 return delegate;
210 }
211
212
213
214
215 public void tableChanged(TableModelEvent e)
216 {
217 enqueue(e);
218 }
219
220 protected void fire(TableModelEvent e)
221 {
222 logger.fine("column= " + e.getColumn() + " row= " + e.getFirstRow()
223 + "-" + e.getLastRow() + " type= " + e.getType());
224
225 TableModelListener[] l = (TableModelListener[])listeners.toArray();
226
227 for (int i = 0; i < l.length; i++) {
228 try {
229 l[i].tableChanged(e);
230 } catch (Exception ex) {
231 ex.printStackTrace();
232 }
233 }
234 }
235
236 protected synchronized void enqueue(TableModelEvent e)
237 {
238 logger.fine("adding column= " + e.getColumn() + " row= "
239 + e.getFirstRow() + "-" + e.getLastRow() + " type= " + e.getType());
240
241 TableModelEvent ev = queue.size() > 0
242 ? (TableModelEvent)queue.getLast() : null;
243
244
245 if (ev != null
246 && (ev.getType() == e.getType()
247
248
249
250
251 || ev.getType() == TableModelEvent.HEADER_ROW)) {
252
253 int col = ev.getColumn();
254
255 if (col != e.getColumn()) {
256 col = TableModelEvent.ALL_COLUMNS;
257 }
258
259 int first = ev.getFirstRow();
260
261 if (first > e.getFirstRow()) {
262 first = e.getFirstRow();
263 }
264
265 int last = ev.getLastRow();
266
267 if (last < e.getLastRow() && last != TableModelEvent.HEADER_ROW) {
268 last = e.getLastRow();
269 }
270
271
272
273 if (col != ev.getColumn() || first != ev.getFirstRow()
274 || last != ev.getLastRow()) {
275 queue.removeLast();
276 logger.fine("added column= " + col + " row= " + first + "-"
277 + last + " type= " + ev.getType());
278 queue.add(new TableModelEvent(this, first, last, col,
279 ev.getType()));
280
281
282
283
284
285
286 updater.update();
287 }
288 } else {
289
290 logger.fine("added column= " + e.getColumn() + " row= "
291 + e.getFirstRow() + "-" + e.getLastRow() + " type= "
292 + e.getType());
293 queue.add(e);
294
295 updater.update();
296 }
297 }
298
299 protected synchronized TableModelEvent dequeue()
300 {
301 return queue.size() > 0 ? queue.removeFirst() : null;
302 }
303
304
305
306
307 public void run()
308 {
309 TableModelEvent e;
310
311 while ((e = dequeue()) != null) {
312
313 if (e.getSource() == this) {
314 fire(e);
315 } else {
316 fire(new TableModelEvent(this, e.getFirstRow(), e.getLastRow(),
317 e.getColumn(), e.getType()));
318 }
319 }
320 }
321
322
323
324
325
326 public int getRelaxationTime() {
327 return relaxationTime;
328 }
329
330
331
332
333
334 public void setRelaxationTime(int relaxationTime) {
335 this.relaxationTime = relaxationTime;
336 updater.update();
337 }
338
339
340
341
342
343 public boolean isDestroyed() {
344 return destroyed;
345 }
346
347
348
349
350
351 public void destroy() {
352 destroyed=true;
353 updater.update();
354
355 delegate.removeTableModelListener(this);
356 listeners.clear();
357 queue.clear();
358 }
359 }
360
361