001    /*
002     * $Id: DefaultVisuals.java 3100 2008-10-14 22:33:10Z rah003 $
003     *
004     * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     * 
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     * 
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    package org.jdesktop.swingx.renderer;
022    
023    import java.awt.Color;
024    import java.io.Serializable;
025    
026    import javax.swing.JComponent;
027    
028    /**
029     * Encapsulates the default visual configuration of renderering components,
030     * respecting the state of the passed-in <code>CellContext</code>. It's
031     * basically re-usable across all types of renderees (JTable, JList, JTree).
032     * <p>
033     * 
034     * Guarantees to completely configure the default visual properties (listed
035     * below) of a given component. As a consequence, client code (f.i. in
036     * <code>Highlighter</code>s) can safely change them without long-lasting
037     * visual artefacts.
038     * 
039     * <ul>
040     * <li> foreground and background, depending on selected and focused state
041     * <li> border
042     * <li> font
043     * <li> Painter (if applicable)
044     * <li> enabled
045     * <li> componentOrientation
046     * <li> toolTipText
047     * <li> minimum-, maximum-, preferredSize
048     * </ul>
049     * 
050     * Client code will rarely need to be aware of this class. It's the single
051     * place to change on introduction of new properties considered as belonging
052     * to the "default visuals" of rendering components. <p>
053     * 
054     * PENDING: allow mutators for overruling the <code>CellContext</code>s
055     * defaults? Would prefer not to, as in the context of SwingX visual config on
056     * the renderer level is discouraged (the way to go are <code>Highlighter</code>s.<p>
057     * 
058     * PENDING: not yet quite decided whether the toolTipText property belongs
059     * into the visual default config. Doing so gives client code the choice to
060     * set it either in a Highlighter or a custom ComponentProvider.
061     * 
062     * @author Jeanette Winzenburg
063     * 
064     * @see CellContext
065     */
066    public class DefaultVisuals<T extends JComponent> implements Serializable {
067    
068    
069        private Color unselectedForeground;
070    
071        private Color unselectedBackground;
072    
073        /**
074         * Sets the renderer's unselected-foreground color to the specified color.
075         * If <code>not null</code> this color will overrule the default color of
076         * the CellContext.
077         * 
078         * @param c set the foreground color to this value
079         */
080        public void setForeground(Color c) {
081            unselectedForeground = c;
082        }
083    
084        /**
085         * Sets the renderer's unselected-background color to the specified color.
086         * If <code>not null</code> this color will overrule the default color of
087         * the CellContext.
088         * 
089         * @param c set the background color to this value
090         */
091        public void setBackground(Color c) {
092            unselectedBackground = c;
093        }
094    
095        
096        //---------------- subclass configuration    
097        /**
098         * Configures all default visual state of the rendering component from the 
099         * given cell context.
100         * 
101         * @param renderingComponent the component to configure, must not be null
102         * @param context the cell context to configure from, must not be null
103         * @throws NullPointerException if either renderingComponent or cellContext 
104         *   is null
105         */
106        public void configureVisuals(T renderingComponent, CellContext context) {
107            configureState(renderingComponent, context);
108            configureColors(renderingComponent, context);
109            configureBorder(renderingComponent, context);
110            configurePainter(renderingComponent, context);
111        }
112    
113        /**
114         * Configures the default Painter if applicable. Here: set's to null.
115         * 
116         * @param renderingComponent the component to configure, must not be null
117         * @param context the cell context to configure from, must not be null
118         */
119        protected void configurePainter(T renderingComponent, CellContext context) {
120            if (renderingComponent instanceof PainterAware) {
121                ((PainterAware) renderingComponent).setPainter(null);
122            }
123            
124        }
125    
126        /**
127         * Configure "divers" visual state of the rendering component from the given
128         * cell context.
129         * <p>
130         * 
131         * Here: synch <code>Font</code>, <code>ComponentOrientation</code> and
132         * <code>enabled</code> to context's component. Resets toolTipText to null.
133         * Calls configureSizes to reset xxSize if appropriate.
134         * <p>
135         * 
136         * PENDING: not fully defined - "divers" means everything that's not 
137         * <code>Color</code>s
138         * nor <code>Border</code> nor <code>Painter</code>.
139         *      
140         * @param renderingComponent the component to configure, must not be null
141         * @param context the cell context to configure from, must not be null
142         */
143        protected void configureState(T renderingComponent, CellContext context) {
144            renderingComponent.setToolTipText(null);
145            configureSizes(renderingComponent, context);
146            if (context.getComponent() == null) {
147                // what to do?
148                // we guarantee to cleanup completely - what are the defaults?
149                // leave the decistion to the context?
150            } else {
151                renderingComponent.setFont(context.getComponent().getFont());
152                renderingComponent.setEnabled(context.getComponent().isEnabled());
153                renderingComponent.applyComponentOrientation(context.getComponent()
154                        .getComponentOrientation());
155            }
156        }
157    
158        /**
159         * Configures min-, max, preferredSize properties of the renderingComponent.
160         * 
161         * Here: set all to null.
162         * 
163         * @param renderingComponent the component to configure, must not be null
164         * @param context the cell context to configure from, must not be null
165         */
166        protected void configureSizes(T renderingComponent, CellContext context) {
167            renderingComponent.setPreferredSize(null);
168            renderingComponent.setMinimumSize(null);
169            renderingComponent.setMaximumSize(null);
170        }
171    
172        /**
173         * Configures colors of rendering component from the given cell context.
174         * 
175         * @param renderingComponent the component to configure, must not be null
176         * @param context the cell context to configure from, must not be null
177         */
178        protected void configureColors(T renderingComponent, CellContext context) {
179            if (context.isSelected()) {
180                renderingComponent.setForeground(context.getSelectionForeground());
181                renderingComponent.setBackground(context.getSelectionBackground());
182            } else {
183                renderingComponent.setForeground(getForeground(context));
184                renderingComponent.setBackground(getBackground(context));
185            }
186            if (context.isFocused()) {
187                configureFocusColors(renderingComponent, context);
188            }
189        }
190        /**
191         * Configures focus-related colors form given cell context.<p>
192         * 
193         * PENDING: move to context as well? - it's the only comp
194         * with focus specifics? Problem is the parameter type...
195         * 
196         * @param renderingComponent the component to configure, must not be null
197         * @param context the cell context to configure from, must not be null
198         */
199        protected void configureFocusColors(T renderingComponent, CellContext context) {
200            if (!context.isSelected() && context.isEditable()) {
201                Color col = context.getFocusForeground();
202                if (col != null) {
203                    renderingComponent.setForeground(col);
204                }
205                col = context.getFocusBackground();
206                if (col != null) {
207                    renderingComponent.setBackground(col);
208                }
209            }
210        }
211    
212    
213        /**
214         * Configures the rendering component's border from the given cell context.<p>
215         * 
216         * @param renderingComponent the component to configure, must not be null
217         * @param context the cell context to configure from, must not be null
218         */
219        protected void configureBorder(T renderingComponent, CellContext context) {
220            renderingComponent.setBorder(context.getBorder());
221        }
222    
223        /**
224         * Returns the unselected foreground to use for the rendering 
225         * component. <p>
226         * 
227         * Here: returns this renderer's unselected foreground is not null,
228         * returns the foreground from the given context. In other words:
229         * the renderer's foreground takes precedence if set.
230         * 
231         * @param context the cell context.
232         * @return the unselected foreground.
233         */
234        protected Color getForeground(CellContext context) {
235            if (unselectedForeground != null)
236                return unselectedForeground;
237            return context.getForeground();
238        }
239    
240        /**
241         * Returns the unselected background to use for the rendering 
242         * component. <p>
243         * 
244         * Here: returns this renderer's unselected background is not null,
245         * returns the background from the given context. In other words:
246         * the renderer's background takes precedence if set.
247         * 
248         * @param context the cell context.
249         * @return the unselected background.
250         */
251        protected Color getBackground(CellContext context) {
252            if (unselectedBackground != null)
253                return unselectedBackground;
254            return context.getBackground();
255        }
256    
257        
258    
259    }