1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.scene.control; 27 28 import javafx.beans.property.ReadOnlyIntegerProperty; 29 import javafx.beans.property.ReadOnlyIntegerWrapper; 30 import javafx.beans.property.ReadOnlyObjectProperty; 31 import javafx.beans.property.ReadOnlyObjectWrapper; 32 import javafx.collections.ListChangeListener; 33 34 /** 35 * SelectionModel is an abstract class used by UI controls to provide a 36 * consistent API for maintaining selection. 37 * 38 * @param <T> The type of the item contained in the control that can be selected. 39 * @since JavaFX 2.0 40 */ 41 public abstract class SelectionModel<T> { 42 43 /*************************************************************************** 44 * * 45 * Selection Properties * 46 * * 47 **************************************************************************/ 48 49 /** 50 * <p>Refers to the selected index property, which is used to indicate 51 * the currently selected index value in the selection model. The selected 52 * index is either -1, 53 * to represent that there is no selection, or an integer value that is within 54 * the range of the underlying data model size. 55 * 56 * <p>The selected index property is most commonly used when the selection 57 * model only allows single selection, but is equally applicable when in 58 * multiple selection mode. When in this mode, the selected index will always 59 * represent the last selection made. 60 * 61 * <p>Note that in the case of multiple selection, it is possible to add 62 * a {@link ListChangeListener} to the collection returned by 63 * {@link MultipleSelectionModel#getSelectedIndices()} to be informed whenever 64 * the selection changes, and this will also work in the case of single selection. 65 * @return the selected index property 66 */ 67 public final ReadOnlyIntegerProperty selectedIndexProperty() { return selectedIndex.getReadOnlyProperty(); } 68 private ReadOnlyIntegerWrapper selectedIndex = new ReadOnlyIntegerWrapper(this, "selectedIndex", -1); 69 protected final void setSelectedIndex(int value) { selectedIndex.set(value); } 70 71 /** 72 * <p>Returns the integer value indicating the currently selected index in 73 * this model. If there are multiple items selected, this will return the 74 * most recent selection made. 75 * 76 * <p>Note that the returned value is a snapshot in time - if you wish to 77 * observe the selection model for changes to the selected index, you can 78 * add a ChangeListener as such: 79 * 80 * <pre><code> 81 * SelectionModel sm = ...; 82 * InvalidationListener listener = ...; 83 * sm.selectedIndexProperty().addListener(listener); 84 * </code></pre> 85 * @return the selected index 86 */ 87 public final int getSelectedIndex() { return selectedIndexProperty().get(); } 88 89 /** 90 * <p>Refers to the selected item property, which is used to indicate 91 * the currently selected item in the selection model. The selected item is 92 * either null, 93 * to represent that there is no selection, or an Object that is retrieved 94 * from the underlying data model of the control the selection model is 95 * associated with. 96 * 97 * <p>The selected item property is most commonly used when the selection 98 * model is set to be single selection, but is equally applicable when in 99 * multiple selection mode. When in this mode, the selected item will always 100 * represent the last selection made. 101 * @return the selected item property 102 */ 103 public final ReadOnlyObjectProperty<T> selectedItemProperty() { return selectedItem.getReadOnlyProperty(); } 104 private ReadOnlyObjectWrapper<T> selectedItem = new ReadOnlyObjectWrapper<T>(this, "selectedItem"); 105 protected final void setSelectedItem(T value) { selectedItem.set(value); } 106 107 /** 108 * Returns the currently selected object (which resides in the selected index 109 * position). If there are multiple items selected, this will return the 110 * object contained at the index returned by getSelectedIndex() (which is 111 * always the index to the most recently selected item). 112 * 113 * <p>Note that the returned value is a snapshot in time - if you wish to 114 * observe the selection model for changes to the selected item, you can 115 * add a ChangeListener as such: 116 * 117 * <pre><code> 118 * SelectionModel sm = ...; 119 * InvalidationListener listener = ...; 120 * sm.selectedItemProperty().addListener(listener); 121 * </code></pre> 122 * @return the selected item 123 */ 124 public final T getSelectedItem() { return selectedItemProperty().get(); } 125 126 127 /*************************************************************************** 128 * * 129 * Constructor * 130 * * 131 **************************************************************************/ 132 133 /** 134 * Creates a default SelectionModel instance. 135 */ 136 public SelectionModel() { } 137 138 139 /*************************************************************************** 140 * * 141 * Selection API * 142 * * 143 **************************************************************************/ 144 145 146 /** 147 * A method that clears any selection prior to setting the selection to the 148 * given index. The purpose of this method is to avoid having to call 149 * {@link #clearSelection()} first, meaning that observers that are listening to 150 * the {@link #selectedIndexProperty() selected index} property will not 151 * see the selected index being temporarily set to -1. 152 * 153 * @param index The index that should be the only selected index in this 154 * selection model. 155 */ 156 public abstract void clearAndSelect(int index); 157 158 /** 159 * <p>This will select the given index in the selection model, assuming the 160 * index is within the valid range (i.e. greater than or equal to zero, and 161 * less than the total number of items in the underlying data model). 162 * 163 * <p>If there is already one or more indices selected in this model, calling 164 * this method will <b>not</b> clear these selections - to do so it is 165 * necessary to first call {@link #clearSelection()}. 166 * 167 * <p>If the index is already selected, it will not be selected again, or 168 * unselected. However, if multiple selection is implemented, then calling 169 * select on an already selected index will have the effect of making the index 170 * the new selected index (as returned by {@link #getSelectedIndex()}. 171 * 172 * @param index The position of the item to select in the selection model. 173 */ 174 public abstract void select(int index); 175 176 /** 177 * <p>This method will attempt to select the index that contains the given 178 * object. It will iterate through the underlying data model until it finds 179 * an item whose value is equal to the given object. At this point it will 180 * stop iterating - this means that this method will not select multiple 181 * indices. 182 * 183 * @param obj The object to attempt to select in the underlying data model. 184 */ 185 public abstract void select(T obj); 186 187 /** 188 * <p>This method will clear the selection of the item in the given index. 189 * If the given index is not selected, nothing will happen. 190 * 191 * @param index The selected item to deselect. 192 */ 193 public abstract void clearSelection(int index); 194 195 /** 196 * <p>Clears the selection model of all selected indices. 197 */ 198 public abstract void clearSelection(); 199 200 /** 201 * <p>Convenience method to inform if the given index is currently selected 202 * in this SelectionModel. Is functionally equivalent to calling 203 * <code>getSelectedIndices().contains(index)</code>. 204 * 205 * @param index The index to check as to whether it is currently selected 206 * or not. 207 * @return True if the given index is selected, false otherwise. 208 */ 209 public abstract boolean isSelected(int index); 210 211 /** 212 * This method is available to test whether there are any selected 213 * indices/items. It will return true if there are <b>no</b> selected items, 214 * and false if there are. 215 * 216 * @return Will return true if there are <b>no</b> selected items, and false 217 * if there are. 218 */ 219 public abstract boolean isEmpty(); 220 221 /** 222 * <p>This method will attempt to select the index directly before the current 223 * focused index. If clearSelection is not called first, this method 224 * will have the result of selecting the previous index, whilst retaining 225 * the selection of any other currently selected indices.</p> 226 * 227 * <p>Calling this method will only succeed if:</p> 228 * 229 * <ul> 230 * <li>There is currently a lead/focused index. 231 * <li>The lead/focus index is not the first index in the control. 232 * <li>The previous index is not already selected. 233 * </ul> 234 * 235 * <p>If any of these conditions is false, no selection event will take 236 * place.</p> 237 */ 238 public abstract void selectPrevious(); 239 240 /** 241 * <p>This method will attempt to select the index directly after the current 242 * focused index. If clearSelection is not called first, this method 243 * will have the result of selecting the next index, whilst retaining 244 * the selection of any other currently selected indices.</p> 245 * 246 * <p>Calling this method will only succeed if:</p> 247 * 248 * <ul> 249 * <li>There is currently a lead/focused index. 250 * <li>The lead/focus index is not the last index in the control. 251 * <li>The next index is not already selected. 252 * </ul> 253 * 254 * <p>If any of these conditions is false, no selection event will take 255 * place.</p> 256 */ 257 public abstract void selectNext(); 258 259 /** 260 * <p>This method will attempt to select the first index in the control. If 261 * clearSelection is not called first, this method 262 * will have the result of selecting the first index, whilst retaining 263 * the selection of any other currently selected indices.</p> 264 * 265 * <p>If the first index is already selected, calling this method will have 266 * no result, and no selection event will take place.</p> 267 */ 268 public abstract void selectFirst(); 269 270 /** 271 * <p>This method will attempt to select the last index in the control. If 272 * clearSelection is not called first, this method 273 * will have the result of selecting the last index, whilst retaining 274 * the selection of any other currently selected indices.</p> 275 * 276 * <p>If the last index is already selected, calling this method will have 277 * no result, and no selection event will take place.</p> 278 */ 279 public abstract void selectLast(); 280 }