001 /* DefaultComboBoxModel.java -- 002 Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 package javax.swing; 039 040 import java.io.Serializable; 041 import java.util.Arrays; 042 import java.util.Vector; 043 044 import 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 */ 057 public 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 }