Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2010, 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;
027
028import javafx.beans.property.ReadOnlyIntegerProperty;
029import javafx.beans.property.ReadOnlyIntegerWrapper;
030import javafx.beans.property.ReadOnlyObjectProperty;
031import javafx.beans.property.ReadOnlyObjectWrapper;
032import javafx.collections.ListChangeListener;
033
034/**
035 * SelectionModel is an abstract class used by UI controls to provide a
036 * consistent API for maintaining selection.
037 * 
038 * @param <T> The type of the item contained in the control that can be selected.
039 */
040public abstract class SelectionModel<T> { 
041
042    /***************************************************************************
043     *                                                                         *
044     * Selection Properties                                                    *
045     *                                                                         *
046     **************************************************************************/
047
048    /**
049     * <p>Refers to the selected index property, which is used to indicate
050     * the currently selected index value in the selection model. The selected 
051     * index is either -1,
052     * to represent that there is no selection, or an integer value that is within
053     * the range of the underlying data model size.
054     *
055     * <p>The selected index property is most commonly used when the selection
056     * model only allows single selection, but is equally applicable when in
057     * multiple selection mode. When in this mode, the selected index will always
058     * represent the last selection made.
059     *
060     * <p>Note that in the case of multiple selection, it is possible to add
061     * a {@link ListChangeListener} to the collection returned by
062     * {@link MultipleSelectionModel#getSelectedIndices()} to be informed whenever
063     * the selection changes, and this will also work in the case of single selection.
064     */
065    public final ReadOnlyIntegerProperty selectedIndexProperty() { return selectedIndex.getReadOnlyProperty(); }
066    private ReadOnlyIntegerWrapper selectedIndex = new ReadOnlyIntegerWrapper(this, "selectedIndex", -1);
067    protected final void setSelectedIndex(int value) { selectedIndex.set(value); }
068    
069    /**
070     * <p>Returns the integer value indicating the currently selected index in 
071     * this model. If there are multiple items selected, this will return the 
072     * most recent selection made.
073     *
074     * <p>Note that the returned value is a snapshot in time - if you wish to
075     * observe the selection model for changes to the selected index, you can
076     * add a ChangeListener as such:
077     *
078     * <pre><code>
079     * SelectionModel sm = ...;
080     * InvalidationListener listener = ...;
081     * sm.selectedIndexProperty().addListener(listener);
082     * </code></pre>
083     */
084    public final int getSelectedIndex() { return selectedIndexProperty().get(); }
085
086    /**
087     * <p>Refers to the selected item property, which is used to indicate
088     * the currently selected item in the selection model. The selected item is
089     * either null,
090     * to represent that there is no selection, or an Object that is retrieved
091     * from the underlying data model of the control the selection model is
092     * associated with.
093     *
094     * <p>The selected item property is most commonly used when the selection
095     * model is set to be single selection, but is equally applicable when in
096     * multiple selection mode. When in this mode, the selected item will always
097     * represent the last selection made.
098     */
099    public final ReadOnlyObjectProperty<T> selectedItemProperty() { return selectedItem.getReadOnlyProperty(); }
100    private ReadOnlyObjectWrapper<T> selectedItem = new ReadOnlyObjectWrapper<T>(this, "selectedItem");
101    protected final void setSelectedItem(T value) { selectedItem.set(value); }
102    
103    /**
104     * Returns the currently selected object (which resides in the selected index
105     * position). If there are multiple items selected, this will return the
106     * object contained at the index returned by getSelectedIndex() (which is
107     * always the index to the most recently selected item).
108     * 
109     * <p>Note that the returned value is a snapshot in time - if you wish to
110     * observe the selection model for changes to the selected item, you can
111     * add a ChangeListener as such:
112     *
113     * <pre><code>
114     * SelectionModel sm = ...;
115     * InvalidationListener listener = ...;
116     * sm.selectedItemProperty().addListener(listener);
117     * </code></pre>
118     */
119    public final T getSelectedItem() { return selectedItemProperty().get(); }
120
121
122    /***************************************************************************
123     *                                                                         *
124     * Constructor                                                             *
125     *                                                                         *
126     **************************************************************************/    
127    
128    /**
129     * Creates a default SelectionModel instance.
130     */
131    public SelectionModel() { }
132    
133
134    /***************************************************************************
135     *                                                                         *
136     * Selection API                                                           *
137     *                                                                         *
138     **************************************************************************/
139    
140
141    /**
142     * A method that clears any selection prior to setting the selection to the
143     * given index. The purpose of this method is to avoid having to call
144     * {@link #clearSelection()} first, meaning that observers that are listening to 
145     * the {@link #selectedIndexProperty() selected index} property will not
146     * see the selected index being temporarily set to -1.
147     * 
148     * @param index The index that should be the only selected index in this
149     *      selection model.
150     */
151    public abstract void clearAndSelect(int index);
152
153    /**
154     * <p>This will select the given index in the selection model, assuming the
155     * index is within the valid range (i.e. greater than or equal to zero, and
156     * less than the total number of items in the underlying data model).
157     *
158     * <p>If there is already one or more indices selected in this model, calling
159     * this method will <b>not</b> clear these selections - to do so it is
160     * necessary to first call {@link #clearSelection()}.
161     *
162     * <p>If the index is already selected, it will not be selected again, or
163     * unselected. However, if multiple selection is implemented, then calling
164     * select on an already selected index will have the effect of making the index
165     * the new selected index (as returned by {@link #getSelectedIndex()}.
166     * 
167     * @param index The position of the item to select in the selection model.
168     */
169    public abstract void select(int index);
170
171    /**
172     * <p>This method will attempt to select the index that contains the given
173     * object. It will iterate through the underlying data model until it finds
174     * an item whose value is equal to the given object. At this point it will
175     * stop iterating - this means that this method will not select multiple
176     * indices.
177     *
178     * @param obj The object to attempt to select in the underlying data model.
179     */
180    public abstract void select(T obj);
181
182    /**
183     * <p>This method will clear the selection of the item in the given index.
184     * If the given index is not selected, nothing will happen.
185     *
186     * @param index The selected item to deselect.
187     */
188    public abstract void clearSelection(int index);
189
190    /**
191     * <p>Clears the selection model of all selected indices.
192     */
193    public abstract void clearSelection();
194
195    /**
196     * <p>Convenience method to inform if the given index is currently selected
197     * in this SelectionModel. Is functionally equivalent to calling
198     * <code>getSelectedIndices().contains(index)</code>.
199     *
200     * @param index The index to check as to whether it is currently selected
201     *      or not.
202     * @return True if the given index is selected, false otherwise.
203     */
204    public abstract boolean isSelected(int index);
205
206    /**
207     * This method is available to test whether there are any selected
208     * indices/items. It will return true if there are <b>no</b> selected items,
209     * and false if there are.
210     *
211     * @return Will return true if there are <b>no</b> selected items, and false
212     *          if there are.
213     */
214    public abstract boolean isEmpty();
215
216    /**
217     * <p>This method will attempt to select the index directly before the current
218     * focused index. If clearSelection is not called first, this method
219     * will have the result of selecting the previous index, whilst retaining
220     * the selection of any other currently selected indices.</p>
221     *
222     * <p>Calling this method will only succeed if:</p>
223     *
224     * <ul>
225     *   <li>There is currently a lead/focused index.
226     *   <li>The lead/focus index is not the first index in the control.
227     *   <li>The previous index is not already selected.
228     * </ul>
229     *
230     * <p>If any of these conditions is false, no selection event will take
231     * place.</p>
232     */
233    public abstract void selectPrevious();
234
235    /**
236     * <p>This method will attempt to select the index directly after the current
237     * focused index. If clearSelection is not called first, this method
238     * will have the result of selecting the next index, whilst retaining
239     * the selection of any other currently selected indices.</p>
240     *
241     * <p>Calling this method will only succeed if:</p>
242     *
243     * <ul>
244     *   <li>There is currently a lead/focused index.
245     *   <li>The lead/focus index is not the last index in the control.
246     *   <li>The next index is not already selected.
247     * </ul>
248     *
249     * <p>If any of these conditions is false, no selection event will take
250     * place.</p>
251     */
252    public abstract void selectNext();
253
254    /**
255     * <p>This method will attempt to select the first index in the control. If
256     * clearSelection is not called first, this method
257     * will have the result of selecting the first index, whilst retaining
258     * the selection of any other currently selected indices.</p>
259     *
260     * <p>If the first index is already selected, calling this method will have
261     * no result, and no selection event will take place.</p>
262     */
263    public abstract void selectFirst();
264
265    /**
266     * <p>This method will attempt to select the last index in the control. If
267     * clearSelection is not called first, this method
268     * will have the result of selecting the last index, whilst retaining
269     * the selection of any other currently selected indices.</p>
270     *
271     * <p>If the last index is already selected, calling this method will have
272     * no result, and no selection event will take place.</p>
273     */
274    public abstract void selectLast();
275}