001    /* DefaultListModel.java --
002       Copyright (C) 2002, 2004, 2005  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.util.Enumeration;
041    import java.util.Vector;
042    
043    /**
044     * The default implementation of {@link AbstractListModel}, used by
045     * {@link javax.swing.JList} and similar objects as the model of a list of
046     * values. The implementation is based on an underlying {@link
047     * java.util.Vector}.
048     *
049     * @author Andrew Selkirk
050     * @author Graydon Hoare (graydon@redhat.com)
051     */
052    
053    public class DefaultListModel extends AbstractListModel
054    {
055      private static final long serialVersionUID = 2315945659722172272L;
056    
057      /**
058       * The vector of elements in this list model.
059       */
060      private Vector elements = new Vector();
061    
062      /**
063       * Gets an element of the list at the provided index.
064       *
065       * @param index The index of the element to get
066       *
067       * @return The object at the given index
068       *
069       * @throws ArrayIndexOutOfBoundsException If the provided index is
070       *     outside the bounds of the list <code>[0, size())</code>
071       */
072      public Object elementAt(int index)
073      {
074        return elements.elementAt(index);
075      }
076    
077      /**
078       * Convert the list to a string representation.
079       *
080       * @return A string representation of the list
081       */
082      public String toString()
083      {
084        return elements.toString();
085      }
086    
087      /**
088       * Gets the first index of a particular element in the list.
089       *
090       * @param element The element to search for
091       *
092       * @return The first index in the list at which an object
093       *     <code>obj</code> exists such that <code>obj.equals(element)</code> is
094       *     <code>true</code>; if no such object exists, the method returns
095       *     <code>-1</code>
096       */
097      public int indexOf(Object element)
098      {
099        return elements.indexOf(element);
100      }
101    
102      /**
103       * Gets the first index of a particular element in a list which occurs
104       * <em>at or after</em> a particular index.
105       *
106       * @param element The element to search for
107       * @param startIndex The index to begin searching at
108       *
109       * @return The first index in the list, greater than or equal to
110       *     <code>startIndex</code>, at which an object <code>obj</code> exists
111       *     such that <code>obj.equals(element)</code> is <code>true</code>; if no
112       *     such object exists, the method returns <code>-1</code>
113       */
114      public int indexOf(Object element, int startIndex)
115      {
116        return elements.indexOf(element, startIndex);
117      }
118    
119      /**
120       * Gets the last index of a particular element in the list.
121       *
122       * @param element The element to search for
123       *
124       * @return The last index in the list at which an object
125       *     <code>obj</code> exists such that <code>obj.equals(element)</code> is
126       *     <code>true</code>; if no such object exists, the method returns
127       *     <code>-1</code>
128       */
129      public int lastIndexOf(Object element)
130      {
131        return elements.lastIndexOf(element);
132      }
133    
134      /**
135       * Gets the last index of a particular element in a list which occurs
136       * <em>at or before</em> a particular index.
137       *
138       * @param element The element to search for
139       * @param endIndex The index to finish searching at
140       *
141       * @return The last index in the list, less than to or equal to
142       *     <code>endIndexIndex</code>, at which an object <code>obj</code> exists
143       *     such that <code>obj.equals(element)</code> is <code>true</code>; if no
144       *     such object exists, the method returns <code>-1</code>
145       */
146      public int lastIndexOf(Object element, int endIndex)
147      {
148        return elements.lastIndexOf(element, endIndex);
149      }
150    
151      /**
152       * Gets the list element at a particular index.
153       *
154       * @param index The index to get the list value at
155       *
156       * @return The list value at the provided index
157       *
158       * @throws ArrayIndexOutOfBoundsException If the provided index is
159       *     outside the bounds of the list <code>[0, size())</code>
160       */
161      public Object get(int index)
162      {
163        return elements.get(index);
164      }
165    
166      /**
167       * Sets the list element at a particular index.
168       *
169       * @param index The list index at which to set a value 
170       * @param element The value to set at the specified index
171       *
172       * @return The value previously held at the specified index
173       *
174       * @throws ArrayIndexOutOfBoundsException If the provided index is
175       *     outside the bounds of the list <code>[0, size())</code>
176       */
177      public Object set(int index, Object element)
178      {
179        Object result;
180        result = elements.set(index, element);
181        fireContentsChanged(this, index, index);
182        return result;
183      }
184    
185      /**
186       * Inserts an element at a particular index in the list. Each element at
187       * index <code>i >= index</code> is shifted to position <code>i + 1</code>.
188       * If <code>index</code> is equal to <code>size()</code>, this is
189       * equivalent to appending an element to the array. Any
190       * <code>index</code> greater than <code>size()</code> is illegal.
191       *
192       * @param index The index to insert the element at
193       * @param element The element to insert at the index
194       *
195       * @throws ArrayIndexOutOfBoundsException If the provided index is
196       *     outside the bounds <code>[0, size()]</code>
197       */
198      public void add(int index, Object element)
199      {
200        elements.add(index, element);
201        fireIntervalAdded(this, index, index);
202      }
203    
204      /**
205       * Inserts an element at the end of the list. This is equivalent to
206       * calling <code>list.add(list.size(), element)</code>.
207       *
208       * @param element The element to add to the list
209       */
210      public void addElement(Object element)
211      {
212        int s = elements.size();
213        elements.add(element);
214        fireIntervalAdded(this, s, s);
215      }
216    
217      /**
218       * Gets the number of elements in the list.
219       *
220       * @return The number of elements in the list
221       */
222      public int size()
223      {
224        return elements.size();
225      }
226    
227      /**
228       * Gets an array containing the elements of the list.
229       *
230       * @return An array of the objects in the list, in the order they occur
231       *     in the list
232       */
233      public Object[] toArray()
234      {
235        return elements.toArray();
236      }
237    
238      /**
239       * Determines whether a particular element is a member of the list.
240       *
241       * @param element The element to search for
242       *
243       * @return <code>true</code> if <code>element</code> is a member of the
244       *     list, otherwise <code>false</code>
245       */
246      public boolean contains(Object element)
247      {
248        return elements.contains(element);
249      }
250    
251      /**
252       * Copies the list into a provided array. The provided array must be at
253       * least as large as the list.
254       *
255       * @param array The array to copy the list into
256       * 
257       * @throws IndexOutOfBoundsException if the array is too small to hold the
258       *     elements of the list
259       */
260      public void copyInto(Object[] array)
261      {
262        elements.copyInto(array);
263      }
264    
265      /**
266       * Erases all the elements of the list, setting the list's size to 0.
267       */
268      public void clear()
269      {
270        int s = elements.size();
271        if (s > 0)
272        {
273          elements.clear();
274          fireIntervalRemoved(this, 0, s - 1);
275        }
276      }
277    
278      /**
279       * Removes the element at a particular index from the list.
280       *
281       * @param index The index of the element to remove
282       *
283       * @return The value at the index, which has been removed from the list
284       *
285       * @throws ArrayIndexOutOfBoundsException If the provided index is
286       *     outside the bounds of the list <code>[0, size())</code>
287       */
288      public Object remove(int index)
289      {
290        Object result;
291        result = elements.remove(index);
292        fireIntervalRemoved(this, index, index);
293        return result;
294      }
295    
296      /**
297       * Determines whether the list is empty.
298       *
299       * @return <code>true</code> if the list is empty, otherwise
300       *     <code>false</code>
301       */
302      public boolean isEmpty()
303      {
304        return elements.isEmpty();
305      }
306    
307      /**
308       * Returns an {@link java.util.Enumeration} over the elements of the list.
309       *
310       * @return A new enumeration which iterates over the list
311       */
312      public Enumeration<?> elements()
313      {
314        return elements.elements();
315      }
316    
317      /**
318       * Sets the capacity of the list to be equal to its size. The list's capacity
319       * is the number of elements it can hold before it needs to be reallocated.
320       * The list's size is the number of elements it currently holds. 
321       */
322      public void trimToSize()
323      {
324        elements.trimToSize();
325      }
326    
327      /**
328       * Ensures that the list's capacity is at least equal to
329       * <code>size</code>. The list's capacity is the number of elements it
330       * can hold before it needs to be reallocated.
331       *
332       * @param size The capacity to ensure the list can hold
333       */
334      public void ensureCapacity(int size)
335      {
336        elements.ensureCapacity(size);
337      }
338    
339      /**
340       * Sets the size of the list to a particular value. If the specified size
341       * is greater than the current size, the values at the excess list
342       * indices are set to <code>null</code>.  If the specified size is less
343       * than the current size, the excess elements are removed from the list.
344       *
345       * @param size The new size to set the list to
346       */
347      public void setSize(int size)
348      {
349        int oldSize = elements.size();
350        elements.setSize(size);
351        if (oldSize < size)
352          {
353            fireIntervalAdded(this, oldSize, size - 1);
354          }
355        else if (oldSize > size)
356          {
357            this.fireIntervalRemoved(this, size, oldSize - 1);
358          }
359      }
360    
361      /**
362       * Gets the capacity of the list. The list's capacity is the number of
363       * elements it can hold before it needs to be reallocated. 
364       *
365       * @return The capacity of the list
366       */
367      public int capacity()
368      {
369        return elements.capacity();
370      }
371    
372      /**
373       * Gets the first element in the list.
374       *
375       * @return The first element in the list
376       */
377      public Object firstElement()
378      {
379        return elements.firstElement();
380      }
381    
382      /**
383       * Gets the last element in the list.
384       *
385       * @return The last element in the list
386       */
387      public Object lastElement()
388      {
389        return elements.lastElement();
390      }
391    
392      /**
393       * Sets the list element at a particular index.
394       *
395       * @param element The value to set at the specified index
396       * @param index The list index at which to set a value 
397       *
398       * @throws ArrayIndexOutOfBoundsException If the provided index is
399       *     outside the bounds of the list <code>[0, size())</code>
400       */
401      public void setElementAt(Object element, int index)
402      {
403        elements.setElementAt(element, index);
404        fireContentsChanged(this, index, index);
405      }
406    
407      /**
408       * Removes the element at a particular index from the list.
409       *
410       * @param index The index of the element to remove
411       *
412       * @throws ArrayIndexOutOfBoundsException If the provided index is
413       *     outside the bounds of the list <code>[0, size())</code>
414       */
415      public void removeElementAt(int index)
416      {
417        elements.remove(index);
418        fireIntervalRemoved(this, index, index);
419      }
420    
421      /**
422       * Inserts an element at a particular index in the list. Each element at
423       * index <code>i >= index</code> is shifted to position <code>i + 1</code>.
424       * If <code>index</code> is equal to <code>size()</code>, this is
425       * equivalent to appending an element to the array. Any
426       * <code>index</code> greater than <code>size()</code> is illegal.
427       *
428       * @param element The element to insert at the index
429       * @param index The index to insert the element at
430       *
431       * @throws ArrayIndexOutOfBoundsException If the provided index is
432       *     outside the bounds <code>[0, size()]</code>
433       */
434      public void insertElementAt(Object element, int index)
435      {
436        elements.insertElementAt(element, index);
437        fireIntervalAdded(this, index, index);
438      }
439    
440      /**
441       * Removes the first occurrence of a particular element in the list. If the
442       * element does not exist in the list, nothing happens.
443       *
444       * @param element The element to remove
445       *
446       * @return <code>true</code> if the element existed in the list (and was
447       *     removed), <code>false</code> otherwise
448       */
449      public boolean removeElement(Object element)
450      {
451        int index;
452        index = elements.indexOf(element);
453        if (index != -1)
454          {
455            elements.remove(index);
456            fireIntervalRemoved(this, index, index);
457            return true;
458          }
459        return false;
460      }
461    
462      /**
463       * Remove all elements in the list.
464       */
465      public void removeAllElements()
466      {
467        int size;
468        size = size();
469        if (size > 0)
470          {
471            elements.clear();
472            fireIntervalRemoved(this, 0, size - 1);
473          }
474      }
475    
476      /**
477       * Remove all elements between <code>startIndex</code> and
478       * <code>endIndex</code> inclusive.
479       *
480       * @param startIndex The first index in the range to remove
481       * @param endIndex The last index in the range to remove
482       *
483       * @throws ArrayIndexOutOfBoundsException if either index is outside the
484       *     valid range of indices for this list <code>[0, size())</code>
485       * @throws IllegalArgumentException if <code>startIndex &gt; endIndex</code>
486       */
487      public void removeRange(int startIndex, int endIndex)
488      {
489        int index;
490        if (startIndex > endIndex)
491          throw new IllegalArgumentException();
492        for (index = endIndex; index >= startIndex; index--)
493          elements.remove(index);
494        fireIntervalRemoved(this, startIndex, endIndex);
495      }
496    
497      /**
498       * Gets the size of the list.
499       *
500       * @return The number of elements currently in the list
501       */
502      public int getSize()
503      {
504        return elements.size();
505      }
506    
507      /**
508       * Gets the list element at a particular index.
509       *
510       * @param index The index to get the list value at
511       *
512       * @return The list value at the provided index
513       *
514       * @throws ArrayIndexOutOfBoundsException If the provided index is
515       *     outside the bounds of the list <code>[0, size())</code>
516       */
517      public Object getElementAt(int index)
518      {
519        return elements.get(index);
520      }
521    }