Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.control.cell;
027
028import static javafx.scene.control.cell.CellUtils.createChoiceBox;
029import javafx.beans.property.ObjectProperty;
030import javafx.beans.property.SimpleObjectProperty;
031import javafx.collections.FXCollections;
032import javafx.collections.ObservableList;
033import javafx.scene.control.ChoiceBox;
034import javafx.scene.control.Label;
035import javafx.scene.control.ListCell;
036import javafx.scene.control.ListView;
037import javafx.util.Callback;
038import javafx.util.StringConverter;
039
040/**
041 * A class containing a {@link ListCell} implementation that draws a 
042 * {@link ChoiceBox} node inside the cell.
043 * 
044 * <p>By default, the ChoiceBoxListCell is rendered as a {@link Label} when not 
045 * being edited, and as a ChoiceBox when in editing mode. The ChoiceBox will, by 
046 * default, stretch to fill the entire list cell.
047 * 
048 * <p>To create a ChoiceBoxListCell, it is necessary to provide zero or more 
049 * items that will be shown to the user when the {@link ChoiceBox} menu is 
050 * showing. These items must be of the same type as the ListView items sequence, 
051 * such that upon selection, they replace the existing value in the 
052 * {@link ListView#itemsProperty() items} list.
053 * 
054 * @param <T> The type of the elements contained within the ListView.
055 * @since 2.2
056 */
057public class ChoiceBoxListCell<T> extends ListCell<T> {
058    
059    /***************************************************************************
060     *                                                                         *
061     * Static cell factories                                                   *
062     *                                                                         *
063     **************************************************************************/
064    
065    /**
066     * Creates a ChoiceBox cell factory for use in {@link ListView} controls. 
067     * By default, the ChoiceBoxCell is rendered as a {@link Label} when not 
068     * being edited, and as a ChoiceBox when in editing mode. The ChoiceBox will, 
069     * by default, stretch to fill the entire list cell.
070     * 
071     * @param <T> The type of the elements contained within the ListView.
072     * @param items Zero or more items that will be shown to the user when the
073     *      {@link ChoiceBox} menu is showing. These items must be of the same 
074     *      type as the ListView items list, such that upon selection, they 
075     *      replace the existing value in the 
076     *      {@link ListView#itemsProperty() items} list.
077     * @return A {@link Callback} that will return a ListCell that is able to 
078     *      work on the type of element contained within the ListView.
079     */
080    public static <T> Callback<ListView<T>, ListCell<T>> forListView(final T... items) {
081        return forListView(FXCollections.observableArrayList(items));
082    }
083    
084    /**
085     * Creates a ChoiceBox cell factory for use in {@link ListView} controls. By
086     * default, the ChoiceBoxCell is rendered as a {@link Label} when not being 
087     * edited, and as a ChoiceBox when in editing mode. The ChoiceBox will, by 
088     * default, stretch to fill the entire list cell.
089     * 
090     * @param <T> The type of the elements contained within the ListView.
091     * @param converter A {@link StringConverter} to convert the given item (of type T) 
092     *      to a String for displaying to the user.
093     * @param items Zero or more items that will be shown to the user when the
094     *      {@link ChoiceBox} menu is showing. These items must be of the same 
095     *      type as the ListView items list, such that upon selection, they 
096     *      replace the existing value in the 
097     *      {@link ListView#itemsProperty() items} list.
098     * @return A {@link Callback} that will return a ListCell that is able to 
099     *      work on the type of element contained within the ListView.
100     */
101    public static <T> Callback<ListView<T>, ListCell<T>> forListView(
102            final StringConverter<T> converter, 
103            final T... items) {
104        return forListView(converter, FXCollections.observableArrayList(items));
105    }
106    
107    /**
108     * Creates a ChoiceBox cell factory for use in {@link ListView} controls. 
109     * By default, the ChoiceBoxCell is rendered as a {@link Label} when not 
110     * being edited, and as a ChoiceBox when in editing mode. The ChoiceBox 
111     * will, by default, stretch to fill the entire list cell.
112     * 
113     * @param <T> The type of the elements contained within the ListView.
114     * @param items An {@link ObservableList} containing zero or more items that 
115     *      will be shown to the user when the {@link ChoiceBox} menu is showing. 
116     *      These items must be of the same type as the ListView items sequence, 
117     *      such that upon selection, they replace the existing value in the 
118     *      {@link ListView#itemsProperty() items} list.
119     * @return A {@link Callback} that will return a ListCell that is able to 
120     *      work on the type of element contained within the ListView.
121     */
122    public static <T> Callback<ListView<T>, ListCell<T>> forListView(
123            final ObservableList<T> items) {
124        return forListView(null, items);
125    }
126    
127    /**
128     * Creates a ChoiceBox cell factory for use in {@link ListView} controls. By 
129     * default, the ChoiceBoxCell is rendered as a {@link Label} when not being 
130     * edited, and as a ChoiceBox when in editing mode. The ChoiceBox will, by 
131     * default, stretch to fill the entire list cell.
132     * 
133     * @param <T> The type of the elements contained within the ListView.
134     * @param converter A {@link StringConverter} to convert the given item (of type T) 
135     *      to a String for displaying to the user.
136     * @param items An {@link ObservableList} containing zero or more items that 
137     *      will be shown to the user when the {@link ChoiceBox} menu is showing. 
138     *      These items must be of the same type as the ListView items sequence, 
139     *      such that upon selection, they replace the existing value in the 
140     *      {@link ListView#itemsProperty() items} list.
141     * @return A {@link Callback} that will return a ListCell that is able to 
142     *      work on the type of element contained within the ListView.
143     */
144    public static <T> Callback<ListView<T>, ListCell<T>> forListView(
145            final StringConverter<T> converter, 
146            final ObservableList<T> items) {
147        return new Callback<ListView<T>, ListCell<T>>() {
148            @Override public ListCell<T> call(ListView<T> list) {
149                return new ChoiceBoxListCell<T>(converter, items);
150            }
151        };
152    }
153    
154    
155    
156    /***************************************************************************
157     *                                                                         *
158     * Fields                                                                  *
159     *                                                                         *
160     **************************************************************************/    
161    
162    private final ObservableList<T> items;
163
164    private ChoiceBox<T> choiceBox;
165    
166    
167    
168    /***************************************************************************
169     *                                                                         *
170     * Constructors                                                            *
171     *                                                                         *
172     **************************************************************************/  
173    
174    /**
175     * Creates a default ChoiceBoxListCell with an empty items list.
176     */
177    public ChoiceBoxListCell() {
178        this(FXCollections.<T>observableArrayList());
179    }
180    
181    /**
182     * Creates a default {@link ChoiceBoxListCell} instance with the given items
183     * being used to populate the {@link ChoiceBox} when it is shown.
184     * 
185     * @param items The items to show in the ChoiceBox popup menu when selected 
186     *      by the user.
187     */
188    public ChoiceBoxListCell(T... items) {
189        this(FXCollections.observableArrayList(items));
190    }
191    
192    /**
193     * Creates a {@link ChoiceBoxListCell} instance with the given items
194     * being used to populate the {@link ChoiceBox} when it is shown, and the 
195     * {@link StringConverter} being used to convert the item in to a 
196     * user-readable form.
197     * 
198     * @param converter A {@link StringConverter} that can convert an item of type T 
199     *      into a user-readable string so that it may then be shown in the 
200     *      ChoiceBox popup menu.
201     * @param items The items to show in the ChoiceBox popup menu when selected 
202     *      by the user.
203     */
204    public ChoiceBoxListCell(StringConverter<T> converter, T... items) {
205        this(converter, FXCollections.observableArrayList(items));
206    }
207    
208    /**
209     * Creates a default {@link ChoiceBoxListCell} instance with the given items
210     * being used to populate the {@link ChoiceBox} when it is shown.
211     * 
212     * @param items The items to show in the ChoiceBox popup menu when selected 
213     *      by the user.
214     */
215    public ChoiceBoxListCell(ObservableList<T> items) {
216        this(null, items);
217    }
218
219    /**
220     * Creates a {@link ChoiceBoxListCell} instance with the given items
221     * being used to populate the {@link ChoiceBox} when it is shown, and the 
222     * {@link StringConverter} being used to convert the item in to a 
223     * user-readable form.
224     * 
225     * @param converter A {@link StringConverter} that can convert an item of type T 
226     *      into a user-readable string so that it may then be shown in the 
227     *      ChoiceBox popup menu.
228     * @param items The items to show in the ChoiceBox popup menu when selected 
229     *      by the user.
230     */
231    public ChoiceBoxListCell(StringConverter<T> converter, ObservableList<T> items) {
232        this.getStyleClass().add("choice-box-list-cell");
233        this.items = items;
234        setConverter(converter != null ? converter : CellUtils.<T>defaultStringConverter());
235    }
236    
237    
238
239    /***************************************************************************
240     *                                                                         *
241     * Properties                                                              *
242     *                                                                         *
243     **************************************************************************/
244    
245    // --- converter
246    private ObjectProperty<StringConverter<T>> converter = 
247            new SimpleObjectProperty<StringConverter<T>>(this, "converter");
248
249    /**
250     * The {@link StringConverter} property.
251     */
252    public final ObjectProperty<StringConverter<T>> converterProperty() { 
253        return converter; 
254    }
255    
256    /** 
257     * Sets the {@link StringConverter} to be used in this cell.
258     */
259    public final void setConverter(StringConverter<T> value) { 
260        converterProperty().set(value); 
261    }
262    
263    /**
264     * Returns the {@link StringConverter} used in this cell.
265     */
266    public final StringConverter<T> getConverter() { 
267        return converterProperty().get(); 
268    }
269    
270    
271    
272    /***************************************************************************
273     *                                                                         *
274     * Public API                                                              *
275     *                                                                         *
276     **************************************************************************/
277    
278    /**
279     * Returns the items to be displayed in the ChoiceBox when it is showing.
280     */
281    public ObservableList<T> getItems() {
282        return items;
283    }
284    
285    /** {@inheritDoc} */
286    @Override public void startEdit() {
287        if (! isEditable() || ! getListView().isEditable()) {
288            return;
289        }
290        
291        if (choiceBox == null) {
292            choiceBox = createChoiceBox(this, items);
293        }
294        
295        choiceBox.getSelectionModel().select(getItem());
296        
297        super.startEdit();
298        setText(null);
299        setGraphic(choiceBox);
300    }
301
302    /** {@inheritDoc} */
303    @Override public void cancelEdit() {
304        super.cancelEdit();
305        
306        setText(getConverter().toString(getItem()));
307        setGraphic(null);
308    }
309    
310    /** {@inheritDoc} */
311    @Override public void updateItem(T item, boolean empty) {
312        super.updateItem(item, empty);
313        CellUtils.updateItem(this, getConverter(), null, null, choiceBox);
314    }
315}