GNU Classpath (0.18) | ||
Frames | No Frames |
1: /* SpinnerListModel.java -- A spinner model backed by a list or an array. 2: Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package javax.swing; 39: 40: import java.io.Serializable; 41: import java.util.ArrayList; 42: import java.util.Arrays; 43: import java.util.List; 44: 45: import javax.swing.event.ChangeEvent; 46: 47: /** 48: * An implementation of <code>SpinnerModel</code> which uses the values 49: * contained within a list or an array. The backing list or array is 50: * only stored as a reference within the class. As a result, changes 51: * made elsewhere to the members of the list or array are reflected by 52: * this model. 53: * <p> 54: * 55: * The model itself inherits a list of <code>ChangeListener</code>s from 56: * <code>AbstractSpinnerModel</code>. As this code is unaware of changes 57: * made to the backing list or array, it is the responsibility of the 58: * application using the model to invoke <code>fireStateChanged()</code>, 59: * in order to notify any <code>ChangeListener</code>s, when the list or array 60: * changes. The model handles notification when the reference itself 61: * is changed via <code>setList()</code> or when the current value is 62: * set directly using <code>setValue()</code>. 63: * 64: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 65: * @see SpinnerModel 66: * @see AbstractSpinnerModel 67: * @see JSpinner 68: * @since 1.4 69: */ 70: 71: public class SpinnerListModel 72: extends AbstractSpinnerModel 73: implements Serializable 74: { 75: /** 76: * For compatability with Sun's JDK 77: */ 78: private static final long serialVersionUID = 3358804052191994516L; 79: 80: /** 81: * The backing list for this model. 82: */ 83: private List list; 84: 85: /** 86: * The current index in the list. 87: */ 88: private transient int index; 89: 90: /** 91: * Constructs a default <code>SpinnerListModel</code>. This 92: * is a model backed by a list containing only the single 93: * <code>String</code> element, "empty". 94: */ 95: public SpinnerListModel() 96: { 97: List defaultList; 98: 99: /* Create an empty list */ 100: defaultList = new ArrayList(); 101: /* Add the string "empty" */ 102: defaultList.add("empty"); 103: /* Set the list */ 104: setList(defaultList); 105: } 106: 107: /** 108: * Constructs a <code>SpinnerListModel</code> using the supplied list. 109: * The model maintains a reference to this list, and returns 110: * consecutive elements in response to calls to <code>getNextValue()</code>. 111: * The initial value is that at position 0, so an initial call 112: * to <code>getValue()</code> returns the same as <code>list.get(0)</code>. 113: * 114: * @param list The list to use for this model. 115: * @throws IllegalArgumentException if the list is null or contains no 116: * elements. 117: * @see SpinnerListModel#getNextValue() 118: * @see SpinnerListModel#getValue() 119: */ 120: public SpinnerListModel(List list) 121: { 122: /* Retain a reference to the valid list */ 123: setList(list); 124: } 125: 126: /** 127: * Constructs a <code>SpinnerListModel</code> using the supplied array. 128: * The model stores a reference to the wrapper list returned by 129: * <code>Arrays.asList()</code>. The wrapper list reflects modifications 130: * in the underlying array, so these changes will also be reflected 131: * by the model. The model produces consecutive elements from the array 132: * in response to calls to <code>getNextValue()</code>. The initial 133: * value returned by <code>getValue()</code> is the same as 134: * <code>array[0]</code>. 135: * 136: * @param array The array to use for this model. 137: * @throws IllegalArgumentException if the array is null or contains 138: * no elements. 139: * @see Arrays#asList(Object[]) 140: * @see SpinnerListModel#getNextValue() 141: * @see SpinnerListModel#getValue() 142: */ 143: public SpinnerListModel(Object[] array) 144: { 145: /* Check for a null or zero-sized array */ 146: if (array == null || array.length == 0) 147: { 148: throw new IllegalArgumentException("The supplied array was invalid."); 149: } 150: /* 151: Retain a reference to a wrapper around the valid array 152: The array, in list form, will be tested again here, but we can't really 153: avoid this -- a null value to Arrays.asList will throw a NullPointerException 154: */ 155: setList(Arrays.asList(array)); 156: } 157: 158: /** 159: * Returns the backing list for this model. 160: * 161: * @return The backing list. 162: */ 163: public List getList() 164: { 165: return list; 166: } 167: 168: /** 169: * Returns the next value from the list, which is the same as the element 170: * stored at the current index + 1. Null is returned if there are no more 171: * values to be returned (the end of the list has been reached). An 172: * ambiguity can occur here, as null may also be returned as a valid list 173: * element. This operation does not change the current value. 174: * 175: * @return The next value from the list or null. 176: */ 177: public Object getNextValue() 178: { 179: /* Check for a next value */ 180: if (index < (list.size() - 1)) 181: { 182: /* Return the element at the next index */ 183: return list.get(index + 1); 184: } 185: else 186: { 187: /* Return null as this is the end of the list */ 188: return null; 189: } 190: } 191: 192: /** 193: * Returns the previous value from the list, which is the same as the element 194: * stored at the current index - 1. Null is returned if there are no more 195: * values to be returned (the start of the list has been reached). An 196: * ambiguity can occur here, as null may also be returned as a valid list 197: * element. This operation does not change the current value. 198: * 199: * @return The previous value from the list or null. 200: */ 201: public Object getPreviousValue() 202: { 203: /* Check for a previous value. */ 204: if (index > 0) 205: { 206: /* Return the element at the previous position */ 207: return list.get(index - 1); 208: } 209: else 210: { 211: /* Return null as this is the start of the list */ 212: return null; 213: } 214: } 215: 216: /** 217: * Returns the current value of the model. Initially, this will 218: * be the element at position 0. On later invocations, this will 219: * be the last element returned by <code>getNextValue()</code> 220: * or <code>getPreviousValue()</code>. 221: * 222: * @return The current value. 223: * @see SpinnerListModel#getPreviousValue() 224: * @see SpinnerListModel#getNextValue() 225: */ 226: public Object getValue() 227: { 228: return list.get(index); 229: } 230: 231: /** 232: * Changes the backing list for this model. The model only stores 233: * a reference to the list, so any changes made to the list elsewhere 234: * will be reflected in the values returned by the model. A 235: * <code>ChangeEvent</code> is fired if the list being used actually 236: * changes (i.e. the new list is not referentially equal (!=) to the 237: * old one). 238: * 239: * @param list The new list to use. 240: * @throws IllegalArgumentException if the list is null or contains 241: * no elements. 242: * @see ChangeEvent 243: */ 244: public void setList(List list) 245: { 246: /* Check for null or zero size list */ 247: if (list == null || list.size() == 0) 248: { 249: throw new IllegalArgumentException("The supplied list was invalid."); 250: } 251: /* Check for a change of referenced list */ 252: if (this.list != list) 253: { 254: /* Store the new list */ 255: this.list = list; 256: /* Notify listeners of a change */ 257: fireStateChanged(); 258: } 259: /* We reset the other values in either case */ 260: /* Set the index to 0 */ 261: index = 0; 262: } 263: 264: /** 265: * Sets the current value of the model to be the one supplied. 266: * The value must exist within the backing list in order for 267: * the change to take place. Otherwise, an exception is thrown. 268: * The value used is the first occurrence of the value within 269: * the backing list. Listeners are notified of this change. 270: * Following the change, <code>getNextValue()</code> and 271: * <code>getPreviousValue()</code> return the objects following 272: * and prior to the supplied value, respectively. 273: * 274: * @param value The requested new value of the list. 275: * @throws IllegalArgumentException if the supplied value does 276: * not exist in the backing list. 277: * @see SpinnerListModel#getPreviousValue() 278: * @see SpinnerListModel#getNextValue() 279: */ 280: public void setValue(Object value) 281: { 282: int valueIndex; 283: 284: /* Search for the value in the list */ 285: valueIndex = list.indexOf(value); 286: /* Check for the value being found */ 287: if (valueIndex == -1) 288: { 289: throw new IllegalArgumentException("The supplied value does not " 290: + "exist in this list"); 291: } 292: /* Make the indices match */ 293: index = valueIndex; 294: /* Notify the listeners */ 295: fireStateChanged(); 296: } 297: 298: }
GNU Classpath (0.18) |