View Javadoc

1   /***
2    * DefaultTableColorModel.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.util.EventListener;
30  
31  import javax.swing.event.EventListenerList;
32  import javax.swing.table.TableModel;
33  
34  import org.jcreme.swing.table.TableColorModel;
35  import org.jcreme.swing.table.TableColorModelEvent;
36  import org.jcreme.swing.table.TableColorModelListener;
37  
38  /***
39   * This a basic implementation of the TableColorModel interface. The only color
40   * effect of this class is to ensure a minimum "distance" between the foreground
41   * and background colors. Other implementations may derive from this class.
42   * 
43   * @author $Author: dbregeon $
44   * @version $Revision: 1.3 $
45   */
46  public class DefaultTableColorModel implements TableColorModel {
47      /***
48       * This is the minimum "distance" between the background and the foreground
49       * colors. This distance ensures that the foreground text is always visible.
50       */
51      protected static final int MINIMUM_COLOR_DISTANCE = 170;
52      
53      /***
54       * The data to use when determining a color.
55       */
56      private transient TableModel dataModel = null;
57  
58      /***
59       * The list of listeners registered for the TableColorModelChanged events.
60       */
61      private final EventListenerList listenerList = new EventListenerList();
62  
63      /***
64       * Gets the list of the listeners registered for the modifications of the
65       * color scheme.
66       * 
67       * @param listenerType
68       *            The class of listeners to retrieve.
69       * @return The list of all listeners of the given type registered in the
70       *         list.
71       */
72      public EventListener[] getListeners(Class listenerType) {
73          return this.listenerList.getListeners(listenerType);
74      }
75  
76      /***
77       * Gives access to the background color of a cell.
78       * 
79       * @param row
80       *            the cell's row.
81       * @param column
82       *            the cell's column.
83       * @param selected
84       *            whether the cell is currently selected or not.
85       * @param renderer
86       *            the renderer used to display the cell.
87       * @return the background color for the cell.
88       */
89      public Color getBackgroundColor(int row, int column, boolean selected,
90              java.awt.Component renderer) {
91          return renderer.getBackground();
92      }
93  
94      /***
95       * Fires a TableColorModelEvent telling registered listeners that the color
96       * scheme has changed.
97       * 
98       * @param e
99       *            The event describing the changes.
100      */
101     protected void fireTableColorModelChanged(TableColorModelEvent e) {
102         Object[] listeners = this.listenerList.getListenerList();
103         for (int i = listeners.length - 2; i >= 0; i -= 2) {
104             if (listeners[i] == TableColorModelListener.class) {
105                 ((TableColorModelListener) listeners[i + 1])
106                         .tableColorModelChanged(e);
107             }
108         }
109     }
110 
111     /***
112      * Enables to add listeners for the modifications of the color scheme.
113      * 
114      * @param l
115      *            the listener to add.
116      */
117     public void addTableColorModelListener(TableColorModelListener l) {
118         this.listenerList.add(TableColorModelListener.class, l);
119     }
120 
121     /***
122      * Unregisters the listener for the modifications of the color model.
123      * 
124      * @param l
125      *            the listener to remove.
126      */
127     public void removeTableColorModelListener(TableColorModelListener l) {
128         this.listenerList.remove(TableColorModelListener.class, l);
129     }
130 
131     /***
132      * Gives access to the foreground color of a cell.
133      * 
134      * @param row
135      *            the cell's row.
136      * @param column
137      *            the cell's column.
138      * @param selected
139      *            whether the cell is currently selected or not.
140      * @param renderer
141      *            the renderer used to display the cell.
142      * @return the foreground color for the cell.
143      */
144     public Color getForegroundColor(int row, int column, boolean selected,
145             java.awt.Component renderer) {
146         Color result = null;
147         Color presentBGColor = renderer.getBackground();
148         Color presentFGColor = renderer.getForeground();
149         if (presentFGColor == null) {
150             presentFGColor = Color.black;
151         }
152         result = presentFGColor;
153         return ensureMinimumDistance(result, presentBGColor);
154     }
155 
156     /***
157      * This method enables to generate a Color that may replace the parameter
158      * fgColor as a foreground Color. When the "distance" between the fgColor
159      * and the bgColor is lesser than MINIMUM_COLOR_DISTANCE, the returned
160      * color's components are: red = Math.max(0, Math.min(255, bgRed +
161      * MINIMUM_COLOR_DISTANCE * (fgRed - bgRed) / d)); green = Math.max(0,
162      * Math.min(255, bgGreen + MINIMUM_COLOR_DISTANCE * (fgGreen - bgGreen) /
163      * d)); blue = Math.max(0, Math.min(255, bgBlue + MINIMUM_COLOR_DISTANCE *
164      * (fgBlue - bgBlue) / d));
165      * 
166      * @param fgColor
167      *            the original foreground color.
168      * @param bgColor
169      *            the original background color.
170      * @return the fgColor parameter or the aforementioned replacement color.
171      */
172     protected Color ensureMinimumDistance(Color fgColor, Color bgColor) {
173         Color result = fgColor;
174         int fgRed = fgColor.getRed();
175         int fgGreen = fgColor.getGreen();
176         int fgBlue = fgColor.getBlue();
177         int bgRed = bgColor.getRed();
178         int bgGreen = bgColor.getGreen();
179         int bgBlue = bgColor.getBlue();
180         int red, green, blue;
181         int d = getDistance(bgColor, fgColor);
182         if (d < MINIMUM_COLOR_DISTANCE) {
183             if (d == 0) {
184                 d = 1;
185             }
186             red = Math.max(0, Math.min(255, bgRed + MINIMUM_COLOR_DISTANCE
187                     * (fgRed - bgRed) / d));
188             green = Math.max(0, Math.min(255, bgGreen + MINIMUM_COLOR_DISTANCE
189                     * (fgGreen - bgGreen) / d));
190             blue = Math.max(0, Math.min(255, bgBlue + MINIMUM_COLOR_DISTANCE
191                     * (fgBlue - bgBlue) / d));
192             result = new Color(red, green, blue);
193         }
194         return result;
195     }
196 
197     /***
198      * This method returns the "distance" between two colors. The distance is
199      * the usual euclidian distance in a three dimension space.
200      * 
201      * @param colorOne
202      *            the first color.
203      * @param colorTwo
204      *            the second color.
205      * @return the euclidian distance between colorOne and colorTwo.
206      */
207     protected int getDistance(Color colorOne, Color colorTwo) {
208         int redDifference = colorTwo.getRed() - colorOne.getRed();
209         int greenDifference = colorTwo.getGreen() - colorOne.getGreen();
210         int blueDifference = colorTwo.getBlue() - colorOne.getBlue();
211         return (int) Math.sqrt((redDifference * redDifference)
212                 + (greenDifference * greenDifference)
213                 + (blueDifference * blueDifference));
214     }
215 
216     /***
217      * This is a convenience method that enables to mix two colors. It may be
218      * used when a TableColorModel implementation needs to mix two layers of
219      * color.
220      * 
221      * @param top
222      *            the color that is on the top layer.
223      * @param bottom
224      *            the color that is on the bottom layer.
225      * @return a mixed color between the two parameter colors. The color has the
226      *         following components: red = 255 - Math.min(255, (6 * (255 -
227      *         bottom.getRed()) + 4 * (255 - top.getRed())) / 10) green = 255 -
228      *         Math.min(255, (6 * (255 - bottom.getGreen()) + 4 * (255 -
229      *         top.getGreen())) / 10) blue = 255 - Math.min(255, (6 * (255 -
230      *         bottom.getBlue()) + 4 * (255 - top.getBlue())) / 10)
231      */
232     protected Color mixColors(Color top, Color bottom) {
233         Color result = null;
234         if ((top != null) && (bottom != null)) {
235             int red = 255 - Math
236                     .min(255, (6 * (255 - bottom.getRed()) + 4 * (255 - top
237                             .getRed())) / 10);
238             int green = 255 - Math
239                     .min(255, (6 * (255 - bottom.getGreen()) + 4 * (255 - top
240                             .getGreen())) / 10);
241             int blue = 255 - Math
242                     .min(255, (6 * (255 - bottom.getBlue()) + 4 * (255 - top
243                             .getBlue())) / 10);
244             result = new Color(red, green, blue);
245         } else {
246             if (top != null) {
247                 result = top;
248             }
249             if (bottom != null) {
250                 result = bottom;
251             }
252         }
253         return result;
254     }
255     
256     
257 	/***
258 	 * @see org.jcreme.swing.table.TableColorModel#getTableModel()
259 	 */
260 	public TableModel getTableModel() {
261 		return this.dataModel;
262 	}
263 	/***
264 	 * @see org.jcreme.swing.table.TableColorModel#setTableModel(javax.swing.table.TableModel)
265 	 */
266 	public void setTableModel(TableModel model) {
267 		this.dataModel = model;
268 	}
269 }