View Javadoc

1   /*
2   Wotonomy: OpenStep design patterns for pure Java applications.
3   Copyright (C) 2000 Blacksmith, Inc.
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, see http://www.gnu.org
17  */
18  
19  package net.wotonomy.ui.swing.components;
20  
21  import java.awt.Color;
22  import java.awt.Component;
23  import java.awt.Font;
24  import java.text.Format;
25  
26  import javax.swing.JTable;
27  import javax.swing.table.DefaultTableCellRenderer;
28  
29  /***
30  * A cell renderer for dealing with formatted content.
31  * Subclasses can specify formats or colors or styles for specific values
32  * or locations in the table by overridding getFormatForContext(),
33  * getForegroundForContext() and/or getBackgroundForContext().
34  *
35  * @author michael@mpowers.net
36  * @version $Revision: 904 $
37  * $Date: 2006-02-18 23:19:05 +0000 (Sat, 18 Feb 2006) $
38  */
39  public class FormattedCellRenderer extends DefaultTableCellRenderer
40  {
41      protected Format currentFormat, defaultFormat;
42      protected Color defaultForeground, defaultBackground;
43      protected Font defaultFont;
44  
45  /***
46  * Default constructor with no specified format.
47  */
48      public FormattedCellRenderer()
49      {
50          this( (Format) null );
51      }
52  
53  /***
54  * Constructor specifying a format for renderered content.
55  */
56     public FormattedCellRenderer( Format aFormat )
57      {
58          currentFormat = null;
59          defaultFormat = aFormat;
60          defaultForeground = super.getForeground();
61          defaultBackground = super.getForeground();
62      }
63  
64  /***
65  * Returns the format currently in use to format cell content.
66  * @return The Format that is currently being used.
67  */
68      public Format getFormat()
69      {
70          return defaultFormat;
71      }
72  
73  /***
74  * Sets the format to be used to format cell content.
75  */
76      public void setFormat( Format aFormat )
77      {
78          defaultFormat = aFormat;
79      }
80  
81  /***
82  * Overrides to retain the default foreground color,
83  * much the same as the DefaultCellRenderer does.
84  * We have to do this because DefaultCellRenderer's
85  * ivars are private.
86  */
87      public void setForeground(Color c) {
88          super.setForeground(c);
89          defaultForeground = c;
90      }
91  
92  /***
93  * Overrides to retain the default background color,
94  * much the same as the DefaultCellRenderer does.
95  * We have to do this because DefaultCellRenderer's
96  * ivars are private.
97  */
98      public void setBackground(Color c) {
99          super.setBackground(c);
100         defaultBackground = c;
101     }
102 
103 /***
104 * Overrides to retain the default font,
105 * much the same as the DefaultCellRenderer does.
106 * We have to do this because DefaultCellRenderer's
107 * ivars are private.
108 */
109     public void setFont(Font f) {
110         super.setFont(f);
111         defaultFont = f;
112     }
113 
114 /***
115 * Overridden to format the value with the appropriate Format.  If the
116 * value cannot be formatted with the Format, the superclass method is called.
117 * @param value An Object to be formatted.
118 */
119     protected void setValue(Object value)
120     {
121         if ( currentFormat != null )
122         {
123             try
124             {
125 
126 // if ( ( value instanceof Number ) && ( value.toString().indexOf( "E" ) != -1 ) )
127 // {
128 //     System.out.println( "FormattedCellRenderer.setValue: format = '" + currentFormat.getClass() + "'" );
129 //     System.out.println( "FormattedCellRenderer.setValue: value = '" + value + "'" );
130 //     System.out.println( "FormattedCellRenderer.setValue: double value = '" + ((Number)value).doubleValue() + "'" );
131 //     System.out.println( "FormattedCellRenderer.setValue: float value = '" + ((Number)value).floatValue() + "'" );
132 //     System.out.println( "FormattedCellRenderer.setValue: converted = '" + currentFormat.format( value ) + "'" );
133 // }
134 
135                 // WORKAROUND: This works around what may be a rounding bug in DecimalFormat. (PR 256/297)
136                 currentFormat.format( ZERO );
137 
138                 // DEBUG: code to test for weird one/zero problem (PR 256/297)
139                 String result = currentFormat.format( value );
140 /* above workaround seems to be working
141                 if ( result.equals( "1" ) )
142                 {
143                     System.out.println( "FormattedCellRenderer.setValue: Could be the ONE/ZERO problem!" );
144                     System.out.println( "FormattedCellRenderer.setValue: format = '" + currentFormat.getClass() + "'" );
145                     System.out.println( "FormattedCellRenderer.setValue: original value = '" + value + "'" );
146                     System.out.println( "FormattedCellRenderer.setValue: result = '" + result + "'" );
147                 }
148 */
149                 setText( result );
150 
151 
152 //                setText( currentFormat.format( value ) );
153                 return;
154             }
155             catch ( IllegalArgumentException exc )
156             {
157                 // fall back on superclass implementation
158             }
159         }
160         super.setValue( value );
161     }
162     
163     // FIXME: remove this when possible
164     private static Double ZERO = new Double( 0.0 );
165 
166 /***
167 * Overridden to call context delegate methods.
168 */
169     public Component getTableCellRendererComponent(JTable table, Object value,
170                      boolean isSelected, boolean hasFocus, int row, int column)
171     {
172         Format format;
173 
174         // allow for context-sensitve formatting
175         format = getFormatForContext( table, value, isSelected, hasFocus, row, column );
176         if ( format != null )
177         {
178             currentFormat = format;
179         }
180         else
181         {
182             currentFormat = defaultFormat;
183         }
184 
185         Color color;
186 
187         // allow for context-sensitve foreground color
188         color = getForegroundForContext( table, value, isSelected, hasFocus, row, column );
189         if ( color != null )
190         {
191             super.setForeground( color );
192         }
193         else
194         {
195             super.setForeground( defaultForeground );
196         }
197 
198         // allow for context-sensitve background color
199         color = getBackgroundForContext( table, value, isSelected, hasFocus, row, column );
200         if ( color != null )
201         {
202             super.setBackground( color );
203         }
204         else
205         {
206             super.setBackground( defaultBackground );
207         }
208 
209         // have to call this here because super defaults to table's font
210         Component result =
211             super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
212         // NOTE: DefaultTableCellRenderer returns itself.
213 
214         // allow for context-sensitve font
215         Font font = getFontForContext( table, value, isSelected, hasFocus, row, column );
216         if ( font != null )
217         {
218             result.setFont( font );
219         }
220         else
221         {
222             result.setFont( defaultFont );
223         }
224 
225         return result;
226 
227     }
228 
229 /***
230 * Override this method to provide a specific format for the
231 * specific cell to be rendered by this component.  Any format
232 * returned by this method will take precedence of the format
233 * specified by setFormat(). <br><br>
234 * This default implementation returns null.
235 * @return A Format for this cell, or null to rely on the the
236 * format specified by setFormat().
237 */
238     public Format getFormatForContext(JTable table, Object value,
239                  boolean isSelected, boolean hasFocus, int row, int column)
240     {
241         return null;
242     }
243 
244 /***
245 * Override this method to provide a foreground color for the renderer.
246 * Because the table specifies colors for selected cells,
247 * these colors will only be used when renderering unselected cells. <br><br>
248 * This default implementation returns null.
249 * @return A Color for the foreground of the cell, or null to rely on
250 * the table's default color scheme.
251 */
252     public Color getForegroundForContext(JTable table, Object value,
253                  boolean isSelected, boolean hasFocus, int row, int column)
254     {
255         return null;
256     }
257 
258 /***
259 * Override this method to provide a background color for the renderer.
260 * Because the table specifies colors for selected cells,
261 * these colors will only be used when renderering unselected cells. <br><br>
262 * This default implementation returns null.
263 * @return A Color for the background of the cell, or null to rely on
264 * the table's default color scheme.
265 */
266     public Color getBackgroundForContext(JTable table, Object value,
267                  boolean isSelected, boolean hasFocus, int row, int column)
268     {
269         return null;
270     }
271 
272 /***
273 * Override this method to provide a font for the renderer.<br><br>
274 * This default implementation returns null.
275 * @return A Font for the cell, or null to rely on the table's default font.
276 */
277     public Font getFontForContext(JTable table, Object value,
278                  boolean isSelected, boolean hasFocus, int row, int column)
279     {
280         return null;
281     }
282 
283 }
284