001    /*
002     * $Id: DefaultListRenderer.java 3286 2009-03-10 12:13:43Z kleopatra $
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    
024    import java.awt.Component;
025    
026    import javax.swing.Icon;
027    import javax.swing.JList;
028    import javax.swing.ListCellRenderer;
029    
030    
031    /**
032     * Adapter to glue SwingX renderer support to core API. It has convenience
033     * constructors to create a LabelProvider, optionally configured with a
034     * StringValue and horizontal alignment. Typically, client code does not
035     * interact with this class except at instantiation time.
036     * <p>
037     * 
038     * Note: core DefaultListCellRenderer shows either an icon or the element's
039     * toString representation, depending on whether or not the given value 
040     * is of type icon or implementors. This renderer's empty/null provider 
041     * constructor takes care of configuring the default provider with a converter
042     * which mimics that behaviour. When instantiating this renderer with
043     * any of the constructors which have converters as parameters,
044     * it's up to the client code to supply the appropriate converter, if needed:
045     * 
046     * 
047     * <pre><code>
048     * StringValue sv = new StringValue() {
049     * 
050     *     public String getString(Object value) {
051     *         if (value instanceof Icon) {
052     *             return &quot;&quot;;
053     *         }
054     *         return StringValue.TO_STRING.getString(value);
055     *     }
056     * 
057     * };
058     * StringValue lv = new MappedValue(sv, IconValue.ICON);
059     * listRenderer = new DefaultListRenderer(lv, alignment);
060     * 
061     * </code></pre>
062     * 
063     * <p>
064     * 
065     * 
066     * @author Jeanette Winzenburg
067     * 
068     * @see ComponentProvider
069     * @see StringValue
070     * @see IconValue
071     * @see MappedValue
072     * 
073     * 
074     */
075    public class DefaultListRenderer extends AbstractRenderer
076        implements ListCellRenderer {
077    
078        protected ListCellContext cellContext;
079    
080        /**
081         * Instantiates a default list renderer with the default component
082         * provider.
083         *
084         */
085        public DefaultListRenderer() {
086            this((ComponentProvider) null);
087        }
088    
089        /**
090         * Instantiates a ListCellRenderer with the given ComponentProvider.
091         * If the provider is null, creates and uses a default. The default
092         * provider is of type <code>LabelProvider</code><p>
093         * 
094         * Note: the default provider is configured with a custom StringValue
095         * which behaves exactly as core DefaultListCellRenderer: depending on 
096         * whether or not given value is of type icon or implementors, it shows 
097         * either the icon or the element's toString.  
098         * 
099         * @param componentProvider the provider of the configured component to
100         *   use for cell rendering
101         */
102        public DefaultListRenderer(ComponentProvider componentProvider) {
103            super(componentProvider);
104            this.cellContext = new ListCellContext();
105        }
106    
107        /**
108         * Instantiates a default table renderer with a default component controller
109         * using the given converter.<p>
110         * 
111         * PENDING JW: how to guarantee core consistent icon handling? Leave to 
112         * client code?
113         * 
114         * @param converter the converter to use for mapping the content value to a
115         *        String representation.
116         * 
117         */
118        public DefaultListRenderer(StringValue converter) {
119            this(new LabelProvider(converter));
120        }
121    
122        /**
123         * Instantiates a default list renderer with a default component
124         * controller using the given converter and horizontal 
125         * alignment. 
126         * 
127         * PENDING JW: how to guarantee core consistent icon handling? Leave to
128         * client code?
129         * 
130         * 
131         * @param converter the converter to use for mapping the
132         *   content value to a String representation.
133         * @param alignment the horizontal alignment.
134         */
135        public DefaultListRenderer(StringValue converter, int alignment) {
136            this(new LabelProvider(converter, alignment));
137        }
138    
139        
140        /**
141         * Instantiates a default list renderer with default component provider
142         * using both converters.
143         * 
144         * @param stringValue the converter to use for the string representation
145         * @param iconValue the converter to use for the icon representation
146         */
147        public DefaultListRenderer(StringValue stringValue, IconValue iconValue) {
148            this(new MappedValue(stringValue, iconValue));
149        }
150    
151        /**
152         * Instantiates a default list renderer with default component provider
153         * using both converters and the given alignment.
154         * 
155         * @param stringValue the converter to use for the string representation
156         * @param iconValue the converter to use for the icon representation
157         * @param alignment the rendering component's horizontal alignment
158         */
159        public DefaultListRenderer(StringValue stringValue, IconValue iconValue,
160                int alignment) {
161            this(new MappedValue(stringValue, iconValue), alignment);
162        }
163    
164        // -------------- implements javax.swing.table.ListCellRenderer
165        /**
166         * 
167         * Returns a configured component, appropriate to render the given
168         * list cell.  
169         * 
170         * @param list the <code>JList</code> to render on
171         * @param value the value to assign to the cell 
172         * @param isSelected true if cell is selected
173         * @param cellHasFocus true if cell has focus
174         * @param index the row index (in view coordinates) of the cell to render
175         * @return a component to render the given list cell.
176         */
177        public Component getListCellRendererComponent(JList list, Object value,
178                int index, boolean isSelected, boolean cellHasFocus) {
179            cellContext.installContext(list, value, index, 0, isSelected,
180                    cellHasFocus, true, true);
181            Component comp = componentController.getRendererComponent(cellContext);
182            // fix issue #1040-swingx: memory leak if value not released
183            cellContext.replaceValue(null);
184            return comp;
185        }
186    
187        /**
188         * {@inheritDoc}
189         */ 
190        @Override
191        protected ComponentProvider createDefaultComponentProvider() {
192            return new LabelProvider(createDefaultStringValue());
193        }
194    
195        /**
196         * Creates and returns the default StringValue for a JList.<p>
197         * This is added to keep consistent with core list rendering which
198         * shows either the Icon (for Icon value types) or the default 
199         * to-string for non-icon types.
200         * 
201         * @return the StringValue to use by default.
202         */
203        private StringValue createDefaultStringValue() {
204            StringValue sv = new StringValue() {
205    
206                public String getString(Object value) {
207                    if (value instanceof Icon) {
208                        return "";
209                    }
210                    return StringValues.TO_STRING.getString(value);
211                }
212    
213            };
214            return new MappedValue(sv, IconValues.ICON);
215        }
216    
217    
218    }
219    
220