001/* DefaultComboBoxModel.java -- 002 Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038package javax.swing; 039 040import java.io.Serializable; 041import java.util.Arrays; 042import java.util.Vector; 043 044import javax.swing.event.ListDataEvent; 045 046 047/** 048 * A model that stores a list of elements and a selected item (which may be 049 * <code>null</code>). Changes to the model are signalled to listeners using 050 * {@link ListDataEvent}. This model is designed for use by the 051 * {@link JComboBox} component. 052 * 053 * @author Andrew Selkirk 054 * @author Olga Rodimina 055 * @author Robert Schuster 056 */ 057public class DefaultComboBoxModel extends AbstractListModel 058 implements MutableComboBoxModel, Serializable 059{ 060 private static final long serialVersionUID = 6698657703676921904L; 061 062 /** 063 * Storage for the elements in the model's list. 064 */ 065 private Vector list; 066 067 /** 068 * The selected item (<code>null</code> indicates no selection). 069 */ 070 private Object selectedItem = null; 071 072 /** 073 * Creates a new model, initially empty. 074 */ 075 public DefaultComboBoxModel() 076 { 077 list = new Vector(); 078 } 079 080 /** 081 * Creates a new model and initializes its item list to the values in the 082 * given array. The selected item is set to the first item in the array, or 083 * <code>null</code> if the array length is zero. 084 * 085 * @param items an array containing items for the model (<code>null</code> 086 * not permitted). 087 * 088 * @throws NullPointerException if <code>items</code> is <code>null</code>. 089 */ 090 public DefaultComboBoxModel(Object[] items) 091 { 092 list = new Vector(Arrays.asList(items)); 093 if (list.size() > 0) 094 selectedItem = list.get(0); 095 } 096 097 /** 098 * Creates a new model and initializes its item list to the values in the 099 * given vector. The selected item is set to the first item in the vector, 100 * or <code>null</code> if the vector length is zero. 101 * 102 * @param vector a vector containing items for the model (<code>null</code> 103 * not permitted). 104 * 105 * @throws NullPointerException if <code>vector</code> is <code>null</code>. 106 */ 107 public DefaultComboBoxModel(Vector<?> vector) 108 { 109 this.list = vector; 110 if (getSize() > 0) 111 selectedItem = vector.get(0); 112 } 113 114 /** 115 * Adds an element to the model's item list and sends a {@link ListDataEvent} 116 * to all registered listeners. If the new element is the first item added 117 * to the list, and the selected item is <code>null</code>, the new element 118 * is set as the selected item. 119 * 120 * @param object item to add to the model's item list. 121 */ 122 public void addElement(Object object) 123 { 124 list.addElement(object); 125 int index = list.size() - 1; 126 fireIntervalAdded(this, index, index); 127 if (list.size() == 1 && selectedItem == null) 128 setSelectedItem(object); 129 } 130 131 /** 132 * Removes the element at the specified index from the model's item list 133 * and sends a {@link ListDataEvent} to all registered listeners. If the 134 * element removed was the selected item, then the preceding element becomes 135 * the new selected item (or the next element, if there is no preceding 136 * element). 137 * 138 * @param index the index of the item to remove. 139 * 140 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 141 * bounds. 142 */ 143 public void removeElementAt(int index) 144 { 145 int selected = getIndexOf(selectedItem); 146 if (selected == index) // choose a new selected item 147 { 148 if (selected > 0) 149 setSelectedItem(getElementAt(selected - 1)); 150 else 151 setSelectedItem(getElementAt(selected + 1)); 152 } 153 list.removeElementAt(index); 154 fireIntervalRemoved(this, index, index); 155 } 156 157 /** 158 * Adds an element at the specified index in the model's item list 159 * and sends a {@link ListDataEvent} to all registered listeners. 160 * 161 * @param object element to insert 162 * @param index index specifing position in the list where given element 163 * should be inserted. 164 * 165 * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of 166 * bounds. 167 * 168 * @see #addElement(Object) 169 */ 170 public void insertElementAt(Object object, int index) 171 { 172 list.insertElementAt(object, index); 173 fireIntervalAdded(this, index, index); 174 } 175 176 /** 177 * Removes an element from the model's item list and sends a 178 * {@link ListDataEvent} to all registered listeners. If the item to be 179 * removed is the current selected item, a new selected item will be set. 180 * If the element is not found in the model's item list, this method does 181 * nothing. 182 * 183 * @param object the element to remove. 184 */ 185 public void removeElement(Object object) 186 { 187 int index = getIndexOf(object); 188 if (index != -1) 189 removeElementAt(index); 190 } 191 192 /** 193 * Removes all the items from the model's item list, resets and selected item 194 * to <code>null</code>, and sends a {@link ListDataEvent} to all registered 195 * listeners. 196 */ 197 public void removeAllElements() 198 { 199 selectedItem = null; 200 int size = getSize(); 201 if (size > 0) 202 { 203 list.clear(); 204 fireIntervalRemoved(this, 0, size - 1); 205 } 206 } 207 208 /** 209 * Returns the number of items in the model's item list. 210 * 211 * @return The number of items in the model's item list. 212 */ 213 public int getSize() 214 { 215 return list.size(); 216 } 217 218 /** 219 * Sets the selected item for the model and sends a {@link ListDataEvent} to 220 * all registered listeners. The start and end index of the event is set to 221 * -1 to indicate the model's selection has changed, and not its contents. 222 * 223 * @param object the new selected item (<code>null</code> permitted). 224 */ 225 public void setSelectedItem(Object object) 226 { 227 // No item is selected and object is null, so no change required. 228 if (selectedItem == null && object == null) 229 return; 230 231 // object is already selected so no change required. 232 if (selectedItem != null && selectedItem.equals(object)) 233 return; 234 235 // Simply return if object is not in the list. 236 if (object != null && getIndexOf(object) == -1) 237 return; 238 239 // Here we know that object is either an item in the list or null. 240 241 // Handle the three change cases: selectedItem is null, object is 242 // non-null; selectedItem is non-null, object is null; 243 // selectedItem is non-null, object is non-null and they're not 244 // equal. 245 selectedItem = object; 246 fireContentsChanged(this, -1, -1); 247 } 248 249 /** 250 * Returns the selected item. 251 * 252 * @return The selected item (possibly <code>null</code>). 253 */ 254 public Object getSelectedItem() 255 { 256 return selectedItem; 257 } 258 259 /** 260 * Returns the element at the specified index in the model's item list. 261 * 262 * @param index the element index. 263 * 264 * @return The element at the specified index in the model's item list, or 265 * <code>null</code> if the <code>index</code> is outside the bounds 266 * of the list. 267 */ 268 public Object getElementAt(int index) 269 { 270 if (index < 0 || index >= list.size()) 271 return null; 272 return list.elementAt(index); 273 } 274 275 /** 276 * Returns the index of the specified element in the model's item list. 277 * 278 * @param object the element. 279 * 280 * @return The index of the specified element in the model's item list. 281 */ 282 public int getIndexOf(Object object) 283 { 284 return list.indexOf(object); 285 } 286}