View Javadoc

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 }