1 /***
2 * ChangeHighlightingColorModel.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) 2002 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.table.colormodel;
27
28 import java.awt.Color;
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 import java.util.Iterator;
32 import java.util.Vector;
33
34 import javax.swing.Timer;
35 import javax.swing.event.TableModelEvent;
36 import javax.swing.event.TableModelListener;
37 import javax.swing.table.TableModel;
38
39 import org.jcreme.swing.table.TableColorModel;
40 import org.jcreme.swing.table.TableColorModelEvent;
41
42 /***
43 * This TableColorModel enables to highlight the changes that occur in a
44 * TableModel. The cells that change are colored (background, foreground or
45 * both) for a short period (blink). This model can be used alone or combined
46 * with another ColorModel. In this case, the colors of the other model will be
47 * temporarily overriden by the highlight colors.
48 *
49 * @author $Author: dbregeon $
50 * @version $Revision: 1.2 $
51 */
52 public class ChangeHighlightingColorModel extends DefaultTableColorModel {
53 /***
54 * This is the number of milliseconds when the modified cell will stay
55 * highlighted.
56 */
57 private int resiliencePeriod = 500;
58
59 /***
60 * The background color for highlighted cells.
61 */
62 private Color backgroundHighlightColor = null;
63
64 /***
65 * The foreground color for highlighted cells.
66 */
67 private Color foregroundHighlightColor = null;
68
69 /***
70 * The model that is used when a cell is not highlighted.
71 */
72 private TableColorModel underlyingModel = null;
73
74 /***
75 * This listener enables to capture the changes of a cell.
76 */
77 private final TableModelListener changeListener;
78
79 /***
80 * This listener is used to unhighlight the cells after a period of time.
81 */
82 private final ActionListener timerListener;
83
84 /***
85 * This is the list of the currently active events (those that currently
86 * provoke a highlight.
87 */
88 private final Vector changeEvents = new Vector();
89
90 /***
91 * Creates a new instance of ChangeHighlightingColorModel
92 */
93 public ChangeHighlightingColorModel() {
94 this.changeListener = new TableModelListener() {
95 public void tableChanged(TableModelEvent e) {
96 Vector events = getChangeEvents();
97 synchronized (events) {
98 events.add(e);
99 }
100 ChangeTimer timer = new ChangeTimer(e, getResiliencePeriod(),
101 getTimerListener());
102 timer.setRepeats(false);
103 timer.start();
104 }
105 };
106 this.timerListener = new ActionListener() {
107 public void actionPerformed(ActionEvent e) {
108 ChangeTimer src = (ChangeTimer) e.getSource();
109 TableModelEvent evt = src.getEvent();
110 int firstRow = evt.getFirstRow();
111 int lastRow = evt.getLastRow();
112 if (lastRow == Integer.MAX_VALUE) {
113 firstRow = TableColorModelEvent.ALL_ROWS;
114 lastRow = TableColorModelEvent.ALL_ROWS;
115 }
116 fireTableColorModelChanged(new TableColorModelEvent(
117 ChangeHighlightingColorModel.this, firstRow, lastRow,
118 evt.getColumn()));
119 Vector events = getChangeEvents();
120 synchronized (events) {
121 events.removeElement(src.getEvent());
122 }
123 }
124 };
125 }
126
127 protected Vector getChangeEvents() {
128 return this.changeEvents;
129 }
130
131 protected ActionListener getTimerListener() {
132 return this.timerListener;
133 }
134
135 /***
136 * Gives access to the background color of a cell.
137 *
138 * @param row
139 * the cell's row.
140 * @param column
141 * the cell's column.
142 * @param selected
143 * whether the cell is currently selected or not.
144 * @param renderer
145 * the renderer used to display the cell.
146 * @return the background color for the cell.
147 */
148 public Color getBackgroundColor(int row, int column, boolean selected,
149 java.awt.Component renderer) {
150 Color result = null;
151 if (this.underlyingModel != null) {
152 result = this.underlyingModel.getBackgroundColor(row, column,
153 selected, renderer);
154 }
155 synchronized (this.changeEvents) {
156 Iterator iter = this.changeEvents.iterator();
157 TableModelEvent evt = null;
158 while (iter.hasNext()) {
159 evt = (TableModelEvent) iter.next();
160 if ((row >= evt.getFirstRow())
161 && (row <= evt.getLastRow())
162 && ((evt.getColumn() == TableModelEvent.ALL_COLUMNS) || (column == evt
163 .getColumn()))) {
164 result = this.backgroundHighlightColor;
165 break;
166 }
167 }
168 }
169 return result;
170 }
171
172 /***
173 * Gives access to the foreground color of a cell.
174 *
175 * @param row
176 * the cell's row.
177 * @param column
178 * the cell's column.
179 * @param selected
180 * whether the cell is currently selected or not.
181 * @param renderer
182 * the renderer used to display the cell.
183 * @return the foreground color for the cell.
184 */
185 public Color getForegroundColor(int row, int column, boolean selected,
186 java.awt.Component renderer) {
187 Color result = null;
188 if (this.underlyingModel != null) {
189 result = this.underlyingModel.getForegroundColor(row, column,
190 selected, renderer);
191 }
192 synchronized (this.changeEvents) {
193 Iterator iter = this.changeEvents.iterator();
194 TableModelEvent evt = null;
195 while (iter.hasNext()) {
196 evt = (TableModelEvent) iter.next();
197 if ((row >= evt.getFirstRow())
198 && (row <= evt.getLastRow())
199 && ((evt.getColumn() == TableModelEvent.ALL_COLUMNS) || (column == evt
200 .getColumn()))) {
201 result = this.foregroundHighlightColor;
202 break;
203 }
204 }
205 }
206 return result;
207 }
208
209 /***
210 * Gives access to the background color that is applied when a cell is
211 * highlighted.
212 *
213 * @return the background color used for the highlighted cells.
214 */
215 public Color getBackgroundHighlightColor() {
216 return this.backgroundHighlightColor;
217 }
218
219 /***
220 * Enables to change the background color to apply when highlighting a
221 * change.
222 *
223 * @param color
224 * the background color to use for the highlighted cells.
225 */
226 public void setBackgroundHighlightColor(Color color) {
227 this.backgroundHighlightColor = color;
228 }
229
230 /***
231 * Gives access to the foreground color that is applied when a cell is
232 * highlighted.
233 *
234 * @return the foreground color used for the highlighted cells.
235 */
236 public Color getForegroundHighlightColor() {
237 return this.foregroundHighlightColor;
238 }
239
240 /***
241 * Enables to change the foreground color to apply when highlighting a
242 * change.
243 *
244 * @param color
245 * the foreground color to use for the highlighted cells.
246 */
247 public void setForegroundHighlightColor(Color color) {
248 this.foregroundHighlightColor = color;
249 }
250
251 /***
252 * Gives access to the resilience period (the number of milliseconds that
253 * the highlighting lasts).
254 *
255 * @return the number of milliseconds when the cell stays highlighted after
256 * it changed.
257 */
258 public int getResiliencePeriod() {
259 return this.resiliencePeriod;
260 }
261
262 /***
263 * Enables the change resilience period.
264 *
265 * @param period
266 * the new number of milliseconds for which the cell must stay
267 * highlighted after it changed.
268 */
269 public void setResiliencePeriod(int period) {
270 this.resiliencePeriod = period;
271 }
272
273 /***
274 * Gives access to the underlying TableColorModel.
275 *
276 * @return the underlying TableColorModel.
277 */
278 public TableColorModel getUnderlyingModel() {
279 return this.underlyingModel;
280 }
281
282 /***
283 * Enables to change the underlying TableColorModel.
284 *
285 * @param model
286 * the new underliyng TableColorModel.
287 */
288 public void setUnderlyingModel(TableColorModel model) {
289 this.underlyingModel = model;
290 }
291
292 /***
293 * @see org.jcreme.swing.table.TableColorModel#setTableModel(javax.swing.table.TableModel)
294 */
295 public void setTableModel(TableModel model) {
296 if (getTableModel() != null) {
297 getTableModel().removeTableModelListener(this.changeListener);
298 }
299 super.setTableModel(model);
300 if (model != null) {
301 model.addTableModelListener(this.changeListener);
302 }
303 }
304
305 /***
306 * This class enables to keep track of the event that has to be timed out.
307 */
308 protected class ChangeTimer extends Timer {
309 /***
310 * The event that reported a change we want to time out.
311 */
312 protected TableModelEvent event = null;
313
314 /***
315 * Creates a ChangeTimer.
316 *
317 * @param e
318 * the event to time out.
319 * @param delay
320 * the time out period.
321 * @param listener
322 * the listener that will time the event out.
323 */
324 public ChangeTimer(TableModelEvent e, int delay, ActionListener listener) {
325 super(delay, listener);
326 this.event = e;
327 }
328
329 /***
330 * Gives access to the event that triggered this timer.
331 *
332 * @return the event to time out.
333 */
334 public TableModelEvent getEvent() {
335 return this.event;
336 }
337 }
338 }