Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2011, 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 028/** 029 * A SelectionModel which enforces the requirement that only a single index 030 * be selected at any given time. This class exists for controls that allow for 031 * pluggable selection models, but which do not allow for multiple selection. 032 * A good example is the {@link ChoiceBox} control. Conversely, most other 033 * controls ({@link ListView}, {@link TreeView}, {@link TableView}, etc) 034 * require {@link MultipleSelectionModel} implementations (although 035 * MultipleSelectionModel does still allow for single selection to be set via the 036 * {@link MultipleSelectionModel#selectionModeProperty() selectionMode} 037 * property). 038 * 039 * @see SelectionModel 040 * @see MultipleSelectionModel 041 * @see SelectionMode 042 * @param <T> The type of the item contained in the control that can be selected. 043 */ 044public abstract class SingleSelectionModel<T> extends SelectionModel<T> { 045 046 /*************************************************************************** 047 * * 048 * Constructor * 049 * * 050 **************************************************************************/ 051 052 /** 053 * Creates a default SingleSelectionModel instance. 054 */ 055 public SingleSelectionModel() { } 056 057 058 059 /*************************************************************************** 060 * * 061 * Selection API * 062 * * 063 **************************************************************************/ 064 065 /** {@inheritDoc} */ 066 @Override public void clearSelection() { 067 updateSelectedIndex(-1); 068 } 069 070 /** 071 * Clears the selection of the given index, if it is currently selected. 072 */ 073 @Override public void clearSelection(int index) { 074 if (getSelectedIndex() == index) { 075 clearSelection(); 076 } 077 } 078 079 /** {@inheritDoc} */ 080 @Override public boolean isEmpty() { 081 return getItemCount() == 0 || getSelectedIndex() == -1; 082 } 083 084 /** 085 * <p>This method will return true if the given index is the currently 086 * selected index in this SingleSelectionModel.</code>. 087 * 088 * @param index The index to check as to whether it is currently selected 089 * or not. 090 * @return True if the given index is selected, false otherwise. 091 */ 092 @Override public boolean isSelected(int index) { 093 return getSelectedIndex() == index; 094 } 095 096 /** 097 * In the SingleSelectionModel, this method is functionally equivalent to 098 * calling <code>select(index)</code>, as only one selection is allowed at 099 * a time. 100 */ 101 @Override public void clearAndSelect(int index) { 102 select(index); 103 } 104 105 /** 106 * Selects the index for the first instance of given object in the underlying 107 * data model. Since the SingleSelectionModel can 108 * only support having a single index selected at a time, this also causes 109 * any previously selected index to be unselected. 110 */ 111 @Override public void select(T obj) { 112 if (obj == null) { 113 setSelectedIndex(-1); 114 setSelectedItem(null); 115 return; 116 } 117 118 final int itemCount = getItemCount(); 119 120 for (int i = 0; i < itemCount; i++) { 121 final T value = getModelItem(i); 122 if (value != null && value.equals(obj)) { 123 select(i); 124 return; 125 } 126 } 127 128 // if we are here, we did not find the item in the entire data model. 129 // Even still, we allow for this item to be set to the give object. 130 // We expect that in concrete subclasses of this class we observe the 131 // data model such that we check to see if the given item exists in it, 132 // whilst SelectedIndex == -1 && SelectedItem != null. 133 setSelectedItem(obj); 134 } 135 136 /** 137 * Selects the given index. Since the SingleSelectionModel can only support having 138 * a single index selected at a time, this also causes any previously selected 139 * index to be unselected. 140 */ 141 @Override public void select(int index) { 142 if (index == -1) { 143 clearSelection(); 144 return; 145 } 146 final int itemCount = getItemCount(); 147 if (itemCount == 0 || index < 0 || index >= itemCount) return; 148 updateSelectedIndex(index); 149 } 150 151 /** 152 * Selects the previous index. Since the SingleSelectionModel can only support having 153 * a single index selected at a time, this also causes any previously selected 154 * index to be unselected. 155 */ 156 @Override public void selectPrevious() { 157 if (getSelectedIndex() == 0) return; 158 select(getSelectedIndex() - 1); 159 } 160 161 /** 162 * Selects the next index. Since the SingleSelectionModel can only support having 163 * a single index selected at a time, this also causes any previously selected 164 * index to be unselected. 165 */ 166 @Override public void selectNext() { 167 select(getSelectedIndex() + 1); 168 } 169 170 /** 171 * Selects the first index. Since the SingleSelectionModel can only support having 172 * a single index selected at a time, this also causes any previously selected 173 * index to be unselected. 174 */ 175 @Override public void selectFirst() { 176 if (getItemCount() > 0) { 177 select(0); 178 } 179 } 180 181 /** 182 * Selects the last index. Since the SingleSelectionModel can only support having 183 * a single index selected at a time, this also causes any previously selected 184 * index to be unselected. 185 */ 186 @Override public void selectLast() { 187 int numItems = getItemCount(); 188 if (numItems > 0 && getSelectedIndex() < numItems - 1) { 189 select(numItems - 1); 190 } 191 } 192 193 /** 194 * Gets the data model item associated with a specific index. 195 * @param index The position of the item in the underlying data model. 196 * @return The item that exists at the given index. 197 */ 198 protected abstract T getModelItem(int index); 199 200 /** 201 * Gets the number of items available for the selection model. If the number 202 * of items can change dynamically, it is the responsibility of the 203 * concrete SingleSelectionModel implementation to ensure that items are 204 * selected or unselected as appropriate as the items change. 205 * @return A number greater than or equal to 0. 206 */ 207 protected abstract int getItemCount(); 208 209 // Private Implementation 210 private void updateSelectedIndex(int newIndex) { 211 int currentIndex = getSelectedIndex(); 212 T currentItem = getSelectedItem(); 213 214 setSelectedIndex(newIndex); 215 216 if (currentIndex == -1 && currentItem != null && newIndex == -1) { 217 // no-op: the current selection isn't in the underlying data model - 218 // we should keep the selected item as the new index is -1 219 } else { 220 setSelectedItem(getModelItem(newIndex)); 221 } 222 } 223}