GNU Classpath (0.17) | ||
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: /** 46: * An implementation of <code>SpinnerModel</code> which uses the values 47: * contained within a list or an array. The backing list or array is 48: * only stored as a reference within the class. As a result, changes 49: * made elsewhere to the members of the list or array are reflected by 50: * this model. 51: * <p> 52: * 53: * The model itself inherits a list of <code>ChangeListener</code>s from 54: * <code>AbstractSpinnerModel</code>. As this code is unaware of changes 55: * made to the backing list or array, it is the responsibility of the 56: * application using the model to invoke <code>fireStateChanged()</code>, 57: * in order to notify any <code>ChangeListener</code>s, when the list or array 58: * changes. The model handles notification when the reference itself 59: * is changed via <code>setList()</code> or when the current value is 60: * set directly using <code>setValue()</code>. 61: * 62: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 63: * @see SpinnerModel 64: * @see AbstractSpinnerModel 65: * @see JSpinner 66: * @since 1.4 67: */ 68: 69: public class SpinnerListModel 70: extends AbstractSpinnerModel 71: implements Serializable 72: { 73: /** 74: * For compatability with Sun's JDK 75: */ 76: private static final long serialVersionUID = 3358804052191994516L; 77: 78: /** 79: * The backing list for this model. 80: */ 81: private List list; 82: 83: /** 84: * The current index in the list. 85: */ 86: private transient int index; 87: 88: /** 89: * Constructs a default <code>SpinnerListModel</code>. This 90: * is a model backed by a list containing only the single 91: * <code>String</code> element, "empty". 92: */ 93: public SpinnerListModel() 94: { 95: List defaultList; 96: 97: /* Create an empty list */ 98: defaultList = new ArrayList(); 99: /* Add the string "empty" */ 100: defaultList.add("empty"); 101: /* Set the list */ 102: setList(defaultList); 103: } 104: 105: /** 106: * Constructs a <code>SpinnerListModel</code> using the supplied list. 107: * The model maintains a reference to this list, and returns 108: * consecutive elements in response to calls to <code>getNextValue()</code>. 109: * The initial value is that at position 0, so an initial call 110: * to <code>getValue()</code> returns the same as <code>list.get(0)</code>. 111: * 112: * @param list The list to use for this model. 113: * @throws IllegalArgumentException if the list is null or contains no 114: * elements. 115: * @see SpinnerListModel#getNextValue() 116: * @see SpinnerListModel#getValue() 117: */ 118: public SpinnerListModel(List list) 119: { 120: /* Retain a reference to the valid list */ 121: setList(list); 122: } 123: 124: /** 125: * Constructs a <code>SpinnerListModel</code> using the supplied array. 126: * The model stores a reference to the wrapper list returned by 127: * <code>Arrays.asList()</code>. The wrapper list reflects modifications 128: * in the underlying array, so these changes will also be reflected 129: * by the model. The model produces consecutive elements from the array 130: * in response to calls to <code>getNextValue()</code>. The initial 131: * value returned by <code>getValue()</code> is the same as 132: * <code>array[0]</code>. 133: * 134: * @param array The array to use for this model. 135: * @throws IllegalArgumentException if the array is null or contains 136: * no elements. 137: * @see Arrays#asList(Object[]) 138: * @see SpinnerListModel#getNextValue() 139: * @see SpinnerListModel#getValue() 140: */ 141: public SpinnerListModel(Object[] array) 142: { 143: /* Check for a null or zero-sized array */ 144: if (array == null || array.length == 0) 145: { 146: throw new IllegalArgumentException("The supplied array was invalid."); 147: } 148: /* 149: Retain a reference to a wrapper around the valid array 150: The array, in list form, will be tested again here, but we can't really 151: avoid this -- a null value to Arrays.asList will throw a NullPointerException 152: */ 153: setList(Arrays.asList(array)); 154: } 155: 156: /** 157: * Returns the backing list for this model. 158: * 159: * @return The backing list. 160: */ 161: public List getList() 162: { 163: return list; 164: } 165: 166: /** 167: * Returns the next value from the list, which is the same as the element 168: * stored at the current index + 1. Null is returned if there are no more 169: * values to be returned (the end of the list has been reached). An 170: * ambiguity can occur here, as null may also be returned as a valid list 171: * element. This operation does not change the current value. 172: * 173: * @return The next value from the list or null. 174: */ 175: public Object getNextValue() 176: { 177: /* Check for a next value */ 178: if (index < (list.size() - 1)) 179: { 180: /* Return the element at the next index */ 181: return list.get(index + 1); 182: } 183: else 184: { 185: /* Return null as this is the end of the list */ 186: return null; 187: } 188: } 189: 190: /** 191: * Returns the previous value from the list, which is the same as the element 192: * stored at the current index - 1. Null is returned if there are no more 193: * values to be returned (the start of the list has been reached). An 194: * ambiguity can occur here, as null may also be returned as a valid list 195: * element. This operation does not change the current value. 196: * 197: * @return The previous value from the list or null. 198: */ 199: public Object getPreviousValue() 200: { 201: /* Check for a previous value. */ 202: if (index > 0) 203: { 204: /* Return the element at the previous position */ 205: return list.get(index - 1); 206: } 207: else 208: { 209: /* Return null as this is the start of the list */ 210: return null; 211: } 212: } 213: 214: /** 215: * Returns the current value of the model. Initially, this will 216: * be the element at position 0. On later invocations, this will 217: * be the last element returned by <code>getNextValue()</code> 218: * or <code>getPreviousValue()</code>. 219: * 220: * @return The current value. 221: * @see SpinnerListModel#getPreviousValue() 222: * @see SpinnerListModel#getNextValue() 223: */ 224: public Object getValue() 225: { 226: return list.get(index); 227: } 228: 229: /** 230: * Changes the backing list for this model. The model only stores 231: * a reference to the list, so any changes made to the list elsewhere 232: * will be reflected in the values returned by the model. A 233: * <code>ChangeEvent</code> is fired if the list being used actually 234: * changes (i.e. the new list is not referentially equal (!=) to the 235: * old one). 236: * 237: * @param list The new list to use. 238: * @throws IllegalArgumentException if the list is null or contains 239: * no elements. 240: * @see ChangeEvent 241: */ 242: public void setList(List list) 243: { 244: /* Check for null or zero size list */ 245: if (list == null || list.size() == 0) 246: { 247: throw new IllegalArgumentException("The supplied list was invalid."); 248: } 249: /* Check for a change of referenced list */ 250: if (this.list != list) 251: { 252: /* Store the new list */ 253: this.list = list; 254: /* Notify listeners of a change */ 255: fireStateChanged(); 256: } 257: /* We reset the other values in either case */ 258: /* Set the index to 0 */ 259: index = 0; 260: } 261: 262: /** 263: * Sets the current value of the model to be the one supplied. 264: * The value must exist within the backing list in order for 265: * the change to take place. Otherwise, an exception is thrown. 266: * The value used is the first occurrence of the value within 267: * the backing list. Listeners are notified of this change. 268: * Following the change, <code>getNextValue()</code> and 269: * <code>getPreviousValue()</code> return the objects following 270: * and prior to the supplied value, respectively. 271: * 272: * @param value The requested new value of the list. 273: * @throws IllegalArgumentException if the supplied value does 274: * not exist in the backing list. 275: * @see SpinnerListModel#getPreviousValue() 276: * @see SpinnerListModel#getNextValue() 277: */ 278: public void setValue(Object value) 279: { 280: int valueIndex; 281: 282: /* Search for the value in the list */ 283: valueIndex = list.indexOf(value); 284: /* Check for the value being found */ 285: if (valueIndex == -1) 286: { 287: throw new IllegalArgumentException("The supplied value does not " 288: + "exist in this list"); 289: } 290: /* Make the indices match */ 291: index = valueIndex; 292: /* Notify the listeners */ 293: fireStateChanged(); 294: } 295: 296: }
GNU Classpath (0.17) |