KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdesktop > swing > decorator > Highlighter


1 /*
2  * $Id: Highlighter.java,v 1.3 2004/10/14 01:28:20 davidson1 Exp $
3  *
4  * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
5  * Santa Clara, California 95054, U.S.A. All rights reserved.
6  */

7
8 package org.jdesktop.swing.decorator;
9
10 import java.awt.Color JavaDoc;
11 import java.awt.Component JavaDoc;
12
13 /**
14  * <p><code>Highlighter</code> is a lightweight mechanism to modify the behavior
15  * and attributes of cell renderers such as {@link javax.swing.ListCellRenderer},
16  * {@link javax.swing.table.TableCellRenderer}, and
17  * {@link javax.swing.tree.TreeCellRenderer} in a simple layered fashion.
18  * While cell renderers are split along component lines, highlighters provide a
19  * <em>common interface</em> for decorating cell renderers.
20  * <code>Highlighter</code> achieves this by vectoring access to all component-specific
21  * state and functionality through a {@link ComponentAdapter} object.</p>
22  *
23  * <p>The primary purpose of <code>Highlighter</code> is to decorate a cell
24  * renderer in <em>controlled</em> ways, such as by applying a different color
25  * or font to it. For example, {@link AlternateRowHighlighter} highlights cell
26  * renderers with alternating background colors. In data visualization components
27  * that support multiple columns with potentially different types of data, this
28  * highlighter imparts the same background color consistently across <em>all</em>
29  * columns of the {@link ComponentAdapter#target target} component
30  * regardless of the actual cell renderer registered for any specific column.
31  * Thus, the <code>Highlighter</code> mechanism is orthogonal to the cell
32  * rendering mechanism.</p>
33  *
34  * <p>To use <code>Highlighter</code> you must first set up a
35  * {@link HighlighterPipeline} using an array of <code>Highlighter</code> objects,
36  * and then call setHighlighters() on a data visualization component, passing in
37  * the highligher pipeline. If the array of highlighters is not null and is not
38  * empty, the highlighters are applied to the selected renderer for each cell in
39  * the order they appear in the array.
40  * When it is time to render a cell, the cell renderer is primed as usual, after
41  * which, the {@link Highlighter#highlight highlight} method of the first
42  * highlighter in the {@link HighlighterPipeline} is invoked. The prepared
43  * renderer, and a suitable {@link ComponentAdapter} object is passed to the
44  * <code>highlight</code> method. The highlighter is expected to modify the
45  * renderer in controlled ways, and return the modified renderer (or a substitute)
46  * that is passed to the next highlighter, if any, in the pipeline. The renderer
47  * returned by the <code>highlight</code> method of the last highlighter in the
48  * pipeline is ultimately used to render the cell.</p>
49  *
50  * <p>The <code>Highlighter</code> mechanism enables multiple degrees of
51  * freedom. In addition to specifying the actual cell renderer class, now you
52  * can also specify the number, order, and class of highlighter objects. Using
53  * highlighters is really simple, as shown by the following example:</p>
54  *
55  * <pre>
56   Highlighter[] highlighters = new Highlighter[] {
57       new <b>AlternateRowHighlighter</b>(Color.white,
58                                          new Color(0xF0, 0xF0, 0xE0), null),
59       new <b>PatternHighlighter</b>(null, Color.red, "s.*", 0, 0)
60   };
61
62   HighlighterPipeline highlighterPipeline = new HighlighterPipeline(highlighters);
63   JXTable table = new JXTable();
64   table.setHighlighters(highlighterPipeline);
65  * </pre>
66  *
67  * <p>The above example allocates an array of <code>Highlighter</code> and populates
68  * it with a new {@link AlternateRowHighlighter} and {@link PatternHighlighter}.
69  * The first one in this example highlights all cells in odd rows with a white
70  * background, and all cells in even rows with a silver background, but it does
71  * not specify a foreground color explicitly. The second highlighter does not
72  * specify a background color explicitly, but sets the foreground color to red
73  * <em>if certain conditions are met</em> (see {@link PatternHighlighter} for
74  * more details). In this example, if the cells in the first column of any
75  * row start with the letter 's', then all cells in that row are highlighted with
76  * a red foreground. Also, as mentioned earlier, the highlighters are applied in
77  * the order they appear in the list.</p>
78  *
79  * @author Ramesh Gupta
80  * @see ComponentAdapter
81  * @see javax.swing.ListCellRenderer
82  * @see javax.swing.table.TableCellRenderer
83  * @see javax.swing.tree.TreeCellRenderer
84  */

85 public class Highlighter {
86
87     // Package private field which indicates if the ordinance of the highlighter
88
// will be -1 if uninitialized.
89
int order = -1;
90
91     /**
92      * Predefined <code>Highlighter</code> that highlights the background of
93      * each cell with a pastel green "ledger" background color, and is most
94      * effective when the {@link ComponentAdapter#target} component has
95      * horizontal gridlines in <code>Color.cyan.darker()</code> color.
96      */

97     public final static Highlighter ledgerBackground =
98                 new Highlighter(new Color JavaDoc(0xF5, 0xFF, 0xF5), null);
99
100     /**
101      * Predefined <code>Highlighter</code> that decorates the background of
102      * each cell with a pastel yellow "notepad" background color, and is most
103      * effective when the {@link ComponentAdapter#target} component has
104      * horizontal gridlines in <code>Color.cyan.darker()</code> color.
105      */

106     public final static Highlighter notePadBackground =
107                 new Highlighter(new Color JavaDoc(0xFF, 0xFF, 0xCC), null);
108
109     private Color JavaDoc background = null;
110     private Color JavaDoc foreground = null;
111     private Color JavaDoc selectedBackground = null;
112     private Color JavaDoc selectedForeground = null;
113
114     /**
115      * Default constructor.
116      * Initializes background, foreground, selectedBackground, and
117      * selectedForeground to null.
118      */

119     public Highlighter() {
120         // default constructor
121
}
122
123     /**
124      * Constructs a <code>Highlighter</code> with the specified
125      * background and foreground colors.
126      *
127      * @param cellBackground background color for the renderer, or null,
128      * to compute a suitable background
129      * @param cellForeground foreground color for the renderer, or null,
130      * to compute a suitable foreground
131      */

132     public Highlighter(Color JavaDoc cellBackground, Color JavaDoc cellForeground) {
133         this.background = cellBackground; // could be null
134
this.foreground = cellForeground; // could be null
135
}
136
137     /**
138      * Decorates the specified cell renderer component for the given component
139      * data adapter using highlighters that were previously set for the component.
140      * This method unconditionally invokes {@link #doHighlight doHighlight} with
141      * the same arguments as were passed in.
142      *
143      * @param renderer the cell renderer component that is to be decorated
144      * @param adapter the {@link ComponentAdapter} for this decorate operation
145      * @return the decorated cell renderer component
146      */

147     public Component JavaDoc highlight(Component JavaDoc renderer, ComponentAdapter adapter) {
148         return doHighlight(renderer, adapter);
149     }
150
151     /**
152      * This is the bottleneck decorate method that all highlighters must invoke
153      * to decorate the cell renderer. This method invokes {@link #applyBackground
154      * applyBackground}, {@link #applyForeground applyForeground},
155      * {@link #applyFont applyFont} and so on, to decorate the corresponding
156      * attributes of the specified component within the given adapter.
157      *
158      * @param renderer the cell renderer component that is to be decorated
159      * @param adapter the {@link ComponentAdapter} for this decorate operation
160      * @return the decorated cell renderer component
161      */

162     protected Component JavaDoc doHighlight(Component JavaDoc renderer, ComponentAdapter adapter) {
163         applyBackground(renderer, adapter);
164         applyForeground(renderer, adapter);
165         applyFont(renderer, adapter); // e.g., make it bold
166
// and so on...
167
return renderer;
168     }
169
170     /**
171      * Computes a suitable background for the renderer component within the
172      * specified adapter by calling {@link #computeBackground computeBackground}
173      * and applies the computed color to the component. If the computed
174      * color is null, it leaves the background unchanged; Otherwise it sets the
175      * component's background to the computed color.
176      *
177      * @param renderer the cell renderer component that is to be decorated
178      * @param adapter the {@link ComponentAdapter} for this decorate operation
179      */

180     protected void applyBackground(Component JavaDoc renderer, ComponentAdapter adapter) {
181         Color JavaDoc color = computeBackground(renderer, adapter);
182         if (color != null) {
183             renderer.setBackground(color);
184         }
185     }
186
187     /**
188      * Computes a suitable foreground for the renderer component within the
189      * specified adapter by calling {@link #computeForeground computeForeground}
190      * and applies the computed color to the component. If the computed
191      * color is null, it leaves the foreground unchanged; Otherwise it sets the
192      * component's foreground to the computed color.
193      *
194      * @param renderer the cell renderer component that is to be decorated
195      * @param adapter the {@link ComponentAdapter} for this decorate operation
196      */

197     protected void applyForeground(Component JavaDoc renderer, ComponentAdapter adapter) {
198         Color JavaDoc color = computeForeground(renderer, adapter);
199         if (color != null) {
200             renderer.setForeground(color);
201         }
202     }
203
204     /**
205      * Empty method. Override it to change the font of the renderer component.
206      *
207      * @param renderer the cell renderer component that is to be decorated
208      * @param adapter the {@link ComponentAdapter} for this decorate operation
209      */

210     protected void applyFont(Component JavaDoc renderer, ComponentAdapter adapter) {
211         // must be overridden to cause any effect
212
}
213
214     /**
215      * <p>Computes a suitable background for the renderer component within the
216      * specified adapter and returns the computed color. The computed color
217      * depends on two factors: (i) whether the background color for this
218      * <code>Highlighter</code> is null or not, and (ii) whether the cell
219      * identified by the specified adapter
220      * {@link ComponentAdapter#isSelected isSelected} or not.</p>
221      *
222      * <p>If the background color for this <code>Highlighter</code> is not
223      * null, this method starts with an initial value that is equal to that
224      * background color, and proceeds to check the selected state of the cell.
225      * Otherwise, it starts with the background color of the component whose
226      * cell is being rendererd (not the background color of the renderer component
227      * that was passed in), and proceeds to check the selected state of the cell.</p>
228      *
229      * <p>If the cell identified by the specified adapter is selected, this
230      * method returns the value computed by
231      * {@link #computeSelectedBackground computeSelectedBackground} when passed
232      * the initial background color computed earlier. Otherwise, it simply
233      * returns the initial background color computed earlier.</p>
234      *
235      * @param renderer the cell renderer component that is to be decorated
236      * @param adapter the {@link ComponentAdapter} for this decorate operation
237      * @return a suitable background color for the specified component and adapter
238      */

239     protected Color JavaDoc computeBackground(Component JavaDoc renderer, ComponentAdapter adapter) {
240         // If this.background is null, use adapter.target.getBackground();
241
// Never use renderer.getBackground() as the seed in this decorator
242
// class because renderer is too promiscuous!
243
Color JavaDoc seed = background == null ? adapter.target.getBackground() : background;
244         return adapter.isSelected() ? computeSelectedBackground(seed) : seed;
245     }
246
247     /**
248      * <p>Computes a suitable foreground for the renderer component within the
249      * specified adapter and returns the computed color. The computed color
250      * depends on two factors: (i) whether the foreground color for this
251      * <code>Highlighter</code> is null or not, and (ii) whether the cell
252      * identified by the specified adapter
253      * {@link ComponentAdapter#isSelected isSelected} or not.</p>
254      *
255      * <p>If the foreground color for this <code>Highlighter</code> is not
256      * null, this method starts with an initial value that is equal to that
257      * foreground color, and proceeds to check the selected state of the cell.
258      * Otherwise, it starts with the foreground color of the component whose
259      * cell is being rendererd (not the foreground color of the renderer component
260      * that was passed in), and proceeds to check the selected state of the cell.</p>
261      *
262      * <p>If the cell identified by the specified adapter is selected, this
263      * method returns the value computed by
264      * {@link #computeSelectedForeground computeSelectedBackground} when passed
265      * the initial foreground color computed earlier. Otherwise, it simply
266      * returns the initial foreground color computed earlier.</p>
267      *
268      * @param renderer the cell renderer component that is to be decorated
269      * @param adapter the {@link ComponentAdapter} for this decorate operation
270      * @return a suitable foreground color for the specified component and adapter
271      */

272     protected Color JavaDoc computeForeground(Component JavaDoc renderer, ComponentAdapter adapter) {
273         // If this.foreground is null, use adapter.target.getForeground();
274
// Never use renderer.getForeground() as the seed in this decorator
275
// class because renderer is too promiscuous!
276
Color JavaDoc seed = foreground == null ? adapter.target.getForeground() : foreground;
277         return adapter.isSelected() ? computeSelectedForeground(seed) : seed;
278     }
279
280     /**
281      * Computes the selected background color. If the selected background color
282      * of this <code>Highlighter</code> is not null, this method returns that
283      * color. Otherwise, it returns a {@link java.awt.Color#darker} version of
284      * the specified seed color.
285      *
286      * @param seed initial background color; must not be null
287      * @return the background color for a selected cell
288      */

289     protected Color JavaDoc computeSelectedBackground(Color JavaDoc seed) {
290         return selectedBackground == null ?
291             seed == null ? Color.gray : seed.darker() : selectedBackground;
292     }
293
294     /**
295      * Computes the selected foreground color. If the selected foreground color
296      * of this <code>Highlighter</code> is not null, this method returns that
297      * color. Otherwise, it returns {@link java.awt.Color#white}, ignoring the
298      * specified seed color.
299      *
300      * @param seed initial foreground color
301      * @return the foreground color for a selected cell
302      */

303     protected Color JavaDoc computeSelectedForeground(Color JavaDoc seed) {
304         return selectedForeground == null ? Color.white : selectedForeground;
305     }
306
307     /**
308      * Returns the background color of this <code>Highlighter</code>.
309      *
310      * @return the background color of this <code>Highlighter</code>,
311      * or null, if no background color has been set
312      */

313     public Color JavaDoc getBackground() {
314         return background;
315     }
316
317     /**
318      * Sets the background color of this <code>Highlighter</code>.
319      *
320      * @param color the background color of this <code>Highlighter</code>,
321      * or null, to clear any existing background color
322      */

323     public void setBackground(Color JavaDoc color) {
324         background = color;
325     }
326
327     /**
328      * Returns the foreground color of this <code>Highlighter</code>.
329      *
330      * @return the foreground color of this <code>Highlighter</code>,
331      * or null, if no foreground color has been set
332      */

333     public Color JavaDoc getForeground() {
334         return foreground;
335     }
336
337     /**
338      * Sets the foreground color of this <code>Highlighter</code>.
339      *
340      * @param color the foreground color of this <code>Highlighter</code>,
341      * or null, to clear any existing foreground color
342      */

343     public void setForeground(Color JavaDoc color) {
344         foreground = color;
345     }
346
347     /**
348      * Returns the selected background color of this <code>Highlighter</code>.
349      *
350      * @return the selected background color of this <code>Highlighter</code>,
351      * or null, if no selected background color has been set
352      */

353     public Color JavaDoc getSelectedBackground() {
354         return selectedBackground;
355     }
356
357     /**
358      * Sets the selected background color of this <code>Highlighter</code>.
359      *
360      * @param color the selected background color of this <code>Highlighter</code>,
361      * or null, to clear any existing selected background color
362      */

363     public void setSelectedBackground(Color JavaDoc color) {
364         selectedBackground = color;
365     }
366
367     /**
368      * Returns the selected foreground color of this <code>Highlighter</code>.
369      *
370      * @return the selected foreground color of this <code>Highlighter</code>,
371      * or null, if no selected foreground color has been set
372      */

373     public Color JavaDoc getSelectedForeground() {
374         return selectedForeground;
375     }
376
377     /**
378      * Sets the selected foreground color of this <code>Highlighter</code>.
379      *
380      * @param color the selected foreground color of this <code>Highlighter</code>,
381      * or null, to clear any existing selected foreground color
382      */

383     public void setSelectedForeground(Color JavaDoc color) {
384         selectedForeground = color;
385     }
386
387 }
388
Popular Tags