1 /* 2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing; 27 28 import java.util.Vector; 29 import java.util.Collection; 30 import java.util.Enumeration; 31 32 33 /** 34 * This class loosely implements the <code>java.util.Vector</code> 35 * API, in that it implements the 1.1.x version of 36 * <code>java.util.Vector</code>, has no collection class support, 37 * and notifies the <code>ListDataListener</code>s when changes occur. 38 * Presently it delegates to a <code>Vector</code>, 39 * in a future release it will be a real Collection implementation. 40 * <p> 41 * <strong>Warning:</strong> 42 * Serialized objects of this class will not be compatible with 43 * future Swing releases. The current serialization support is 44 * appropriate for short term storage or RMI between applications running 45 * the same version of Swing. As of 1.4, support for long term storage 46 * of all JavaBeans™ 47 * has been added to the <code>java.beans</code> package. 48 * Please see {@link java.beans.XMLEncoder}. 49 * 50 * @param <E> the type of the elements of this model 51 * 52 * @author Hans Muller 53 * @since 1.2 54 */ 55 @SuppressWarnings("serial") // Same-version serialization only 56 public class DefaultListModel<E> extends AbstractListModel<E> 57 { 58 private Vector<E> delegate = new Vector<E>(); 59 60 /** 61 * Returns the number of components in this list. 62 * <p> 63 * This method is identical to <code>size</code>, which implements the 64 * <code>List</code> interface defined in the 1.2 Collections framework. 65 * This method exists in conjunction with <code>setSize</code> so that 66 * <code>size</code> is identifiable as a JavaBean property. 67 * 68 * @return the number of components in this list 69 * @see #size() 70 */ 71 public int getSize() { 72 return delegate.size(); 73 } 74 75 /** 76 * Returns the component at the specified index. 77 * <blockquote> 78 * <b>Note:</b> Although this method is not deprecated, the preferred 79 * method to use is <code>get(int)</code>, which implements the 80 * <code>List</code> interface defined in the 1.2 Collections framework. 81 * </blockquote> 82 * @param index an index into this list 83 * @return the component at the specified index 84 * @exception ArrayIndexOutOfBoundsException if the <code>index</code> 85 * is negative or greater than the current size of this 86 * list 87 * @see #get(int) 88 */ 89 public E getElementAt(int index) { 90 return delegate.elementAt(index); 91 } 92 93 /** 94 * Copies the components of this list into the specified array. 95 * The array must be big enough to hold all the objects in this list, 96 * else an <code>IndexOutOfBoundsException</code> is thrown. 97 * 98 * @param anArray the array into which the components get copied 99 * @see Vector#copyInto(Object[]) 100 */ 101 public void copyInto(Object anArray[]) { 102 delegate.copyInto(anArray); 103 } 104 105 /** 106 * Trims the capacity of this list to be the list's current size. 107 * 108 * @see Vector#trimToSize() 109 */ 110 public void trimToSize() { 111 delegate.trimToSize(); 112 } 113 114 /** 115 * Increases the capacity of this list, if necessary, to ensure 116 * that it can hold at least the number of components specified by 117 * the minimum capacity argument. 118 * 119 * @param minCapacity the desired minimum capacity 120 * @see Vector#ensureCapacity(int) 121 */ 122 public void ensureCapacity(int minCapacity) { 123 delegate.ensureCapacity(minCapacity); 124 } 125 126 /** 127 * Sets the size of this list. 128 * 129 * @param newSize the new size of this list 130 * @see Vector#setSize(int) 131 */ 132 public void setSize(int newSize) { 133 int oldSize = delegate.size(); 134 delegate.setSize(newSize); 135 if (oldSize > newSize) { 136 fireIntervalRemoved(this, newSize, oldSize-1); 137 } 138 else if (oldSize < newSize) { 139 fireIntervalAdded(this, oldSize, newSize-1); 140 } 141 } 142 143 /** 144 * Returns the current capacity of this list. 145 * 146 * @return the current capacity 147 * @see Vector#capacity() 148 */ 149 public int capacity() { 150 return delegate.capacity(); 151 } 152 153 /** 154 * Returns the number of components in this list. 155 * 156 * @return the number of components in this list 157 * @see Vector#size() 158 */ 159 public int size() { 160 return delegate.size(); 161 } 162 163 /** 164 * Tests whether this list has any components. 165 * 166 * @return <code>true</code> if and only if this list has 167 * no components, that is, its size is zero; 168 * <code>false</code> otherwise 169 * @see Vector#isEmpty() 170 */ 171 public boolean isEmpty() { 172 return delegate.isEmpty(); 173 } 174 175 /** 176 * Returns an enumeration of the components of this list. 177 * 178 * @return an enumeration of the components of this list 179 * @see Vector#elements() 180 */ 181 public Enumeration<E> elements() { 182 return delegate.elements(); 183 } 184 185 /** 186 * Tests whether the specified object is a component in this list. 187 * 188 * @param elem an object 189 * @return <code>true</code> if the specified object 190 * is the same as a component in this list 191 * @see Vector#contains(Object) 192 */ 193 public boolean contains(Object elem) { 194 return delegate.contains(elem); 195 } 196 197 /** 198 * Searches for the first occurrence of <code>elem</code>. 199 * 200 * @param elem an object 201 * @return the index of the first occurrence of the argument in this 202 * list; returns <code>-1</code> if the object is not found 203 * @see Vector#indexOf(Object) 204 */ 205 public int indexOf(Object elem) { 206 return delegate.indexOf(elem); 207 } 208 209 /** 210 * Searches for the first occurrence of <code>elem</code>, beginning 211 * the search at <code>index</code>. 212 * 213 * @param elem an desired component 214 * @param index the index from which to begin searching 215 * @return the index where the first occurrence of <code>elem</code> 216 * is found after <code>index</code>; returns <code>-1</code> 217 * if the <code>elem</code> is not found in the list 218 * @see Vector#indexOf(Object,int) 219 */ 220 public int indexOf(Object elem, int index) { 221 return delegate.indexOf(elem, index); 222 } 223 224 /** 225 * Returns the index of the last occurrence of <code>elem</code>. 226 * 227 * @param elem the desired component 228 * @return the index of the last occurrence of <code>elem</code> 229 * in the list; returns <code>-1</code> if the object is not found 230 * @see Vector#lastIndexOf(Object) 231 */ 232 public int lastIndexOf(Object elem) { 233 return delegate.lastIndexOf(elem); 234 } 235 236 /** 237 * Searches backwards for <code>elem</code>, starting from the 238 * specified index, and returns an index to it. 239 * 240 * @param elem the desired component 241 * @param index the index to start searching from 242 * @return the index of the last occurrence of the <code>elem</code> 243 * in this list at position less than <code>index</code>; 244 * returns <code>-1</code> if the object is not found 245 * @see Vector#lastIndexOf(Object,int) 246 */ 247 public int lastIndexOf(Object elem, int index) { 248 return delegate.lastIndexOf(elem, index); 249 } 250 251 /** 252 * Returns the component at the specified index. 253 * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index 254 * is negative or not less than the size of the list. 255 * <blockquote> 256 * <b>Note:</b> Although this method is not deprecated, the preferred 257 * method to use is <code>get(int)</code>, which implements the 258 * <code>List</code> interface defined in the 1.2 Collections framework. 259 * </blockquote> 260 * 261 * @param index an index into this list 262 * @return the component at the specified index 263 * @see #get(int) 264 * @see Vector#elementAt(int) 265 */ 266 public E elementAt(int index) { 267 return delegate.elementAt(index); 268 } 269 270 /** 271 * Returns the first component of this list. 272 * Throws a <code>NoSuchElementException</code> if this 273 * vector has no components. 274 * @return the first component of this list 275 * @see Vector#firstElement() 276 */ 277 public E firstElement() { 278 return delegate.firstElement(); 279 } 280 281 /** 282 * Returns the last component of the list. 283 * Throws a <code>NoSuchElementException</code> if this vector 284 * has no components. 285 * 286 * @return the last component of the list 287 * @see Vector#lastElement() 288 */ 289 public E lastElement() { 290 return delegate.lastElement(); 291 } 292 293 /** 294 * Sets the component at the specified <code>index</code> of this 295 * list to be the specified element. The previous component at that 296 * position is discarded. 297 * <p> 298 * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index 299 * is invalid. 300 * <blockquote> 301 * <b>Note:</b> Although this method is not deprecated, the preferred 302 * method to use is <code>set(int,Object)</code>, which implements the 303 * <code>List</code> interface defined in the 1.2 Collections framework. 304 * </blockquote> 305 * 306 * @param element what the component is to be set to 307 * @param index the specified index 308 * @see #set(int,Object) 309 * @see Vector#setElementAt(Object,int) 310 */ 311 public void setElementAt(E element, int index) { 312 delegate.setElementAt(element, index); 313 fireContentsChanged(this, index, index); 314 } 315 316 /** 317 * Deletes the component at the specified index. 318 * <p> 319 * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index 320 * is invalid. 321 * <blockquote> 322 * <b>Note:</b> Although this method is not deprecated, the preferred 323 * method to use is <code>remove(int)</code>, which implements the 324 * <code>List</code> interface defined in the 1.2 Collections framework. 325 * </blockquote> 326 * 327 * @param index the index of the object to remove 328 * @see #remove(int) 329 * @see Vector#removeElementAt(int) 330 */ 331 public void removeElementAt(int index) { 332 delegate.removeElementAt(index); 333 fireIntervalRemoved(this, index, index); 334 } 335 336 /** 337 * Inserts the specified element as a component in this list at the 338 * specified <code>index</code>. 339 * <p> 340 * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index 341 * is invalid. 342 * <blockquote> 343 * <b>Note:</b> Although this method is not deprecated, the preferred 344 * method to use is <code>add(int,Object)</code>, which implements the 345 * <code>List</code> interface defined in the 1.2 Collections framework. 346 * </blockquote> 347 * 348 * @param element the component to insert 349 * @param index where to insert the new component 350 * @exception ArrayIndexOutOfBoundsException if the index was invalid 351 * @see #add(int,Object) 352 * @see Vector#insertElementAt(Object,int) 353 */ 354 public void insertElementAt(E element, int index) { 355 delegate.insertElementAt(element, index); 356 fireIntervalAdded(this, index, index); 357 } 358 359 /** 360 * Adds the specified component to the end of this list. 361 * 362 * @param element the component to be added 363 * @see Vector#addElement(Object) 364 */ 365 public void addElement(E element) { 366 int index = delegate.size(); 367 delegate.addElement(element); 368 fireIntervalAdded(this, index, index); 369 } 370 371 /** 372 * Removes the first (lowest-indexed) occurrence of the argument 373 * from this list. 374 * 375 * @param obj the component to be removed 376 * @return <code>true</code> if the argument was a component of this 377 * list; <code>false</code> otherwise 378 * @see Vector#removeElement(Object) 379 */ 380 public boolean removeElement(Object obj) { 381 int index = indexOf(obj); 382 boolean rv = delegate.removeElement(obj); 383 if (index >= 0) { 384 fireIntervalRemoved(this, index, index); 385 } 386 return rv; 387 } 388 389 390 /** 391 * Removes all components from this list and sets its size to zero. 392 * <blockquote> 393 * <b>Note:</b> Although this method is not deprecated, the preferred 394 * method to use is <code>clear</code>, which implements the 395 * <code>List</code> interface defined in the 1.2 Collections framework. 396 * </blockquote> 397 * 398 * @see #clear() 399 * @see Vector#removeAllElements() 400 */ 401 public void removeAllElements() { 402 int index1 = delegate.size()-1; 403 delegate.removeAllElements(); 404 if (index1 >= 0) { 405 fireIntervalRemoved(this, 0, index1); 406 } 407 } 408 409 410 /** 411 * Returns a string that displays and identifies this 412 * object's properties. 413 * 414 * @return a String representation of this object 415 */ 416 public String toString() { 417 return delegate.toString(); 418 } 419 420 421 /* The remaining methods are included for compatibility with the 422 * Java 2 platform Vector class. 423 */ 424 425 /** 426 * Returns an array containing all of the elements in this list in the 427 * correct order. 428 * 429 * @return an array containing the elements of the list 430 * @see Vector#toArray() 431 */ 432 public Object[] toArray() { 433 Object[] rv = new Object[delegate.size()]; 434 delegate.copyInto(rv); 435 return rv; 436 } 437 438 /** 439 * Returns the element at the specified position in this list. 440 * <p> 441 * Throws an <code>ArrayIndexOutOfBoundsException</code> 442 * if the index is out of range 443 * (<code>index < 0 || index >= size()</code>). 444 * 445 * @param index index of element to return 446 * @return the element at the specified position in this list 447 */ 448 public E get(int index) { 449 return delegate.elementAt(index); 450 } 451 452 /** 453 * Replaces the element at the specified position in this list with the 454 * specified element. 455 * <p> 456 * Throws an <code>ArrayIndexOutOfBoundsException</code> 457 * if the index is out of range 458 * (<code>index < 0 || index >= size()</code>). 459 * 460 * @param index index of element to replace 461 * @param element element to be stored at the specified position 462 * @return the element previously at the specified position 463 */ 464 public E set(int index, E element) { 465 E rv = delegate.elementAt(index); 466 delegate.setElementAt(element, index); 467 fireContentsChanged(this, index, index); 468 return rv; 469 } 470 471 /** 472 * Inserts the specified element at the specified position in this list. 473 * <p> 474 * Throws an <code>ArrayIndexOutOfBoundsException</code> if the 475 * index is out of range 476 * (<code>index < 0 || index > size()</code>). 477 * 478 * @param index index at which the specified element is to be inserted 479 * @param element element to be inserted 480 */ 481 public void add(int index, E element) { 482 delegate.insertElementAt(element, index); 483 fireIntervalAdded(this, index, index); 484 } 485 486 /** 487 * Removes the element at the specified position in this list. 488 * Returns the element that was removed from the list. 489 * <p> 490 * Throws an <code>ArrayIndexOutOfBoundsException</code> 491 * if the index is out of range 492 * (<code>index < 0 || index >= size()</code>). 493 * 494 * @param index the index of the element to removed 495 * @return the element previously at the specified position 496 */ 497 public E remove(int index) { 498 E rv = delegate.elementAt(index); 499 delegate.removeElementAt(index); 500 fireIntervalRemoved(this, index, index); 501 return rv; 502 } 503 504 /** 505 * Removes all of the elements from this list. The list will 506 * be empty after this call returns (unless it throws an exception). 507 */ 508 public void clear() { 509 int index1 = delegate.size()-1; 510 delegate.removeAllElements(); 511 if (index1 >= 0) { 512 fireIntervalRemoved(this, 0, index1); 513 } 514 } 515 516 /** 517 * Deletes the components at the specified range of indexes. 518 * The removal is inclusive, so specifying a range of (1,5) 519 * removes the component at index 1 and the component at index 5, 520 * as well as all components in between. 521 * <p> 522 * Throws an <code>ArrayIndexOutOfBoundsException</code> 523 * if the index was invalid. 524 * Throws an <code>IllegalArgumentException</code> if 525 * <code>fromIndex > toIndex</code>. 526 * 527 * @param fromIndex the index of the lower end of the range 528 * @param toIndex the index of the upper end of the range 529 * @see #remove(int) 530 */ 531 public void removeRange(int fromIndex, int toIndex) { 532 if (fromIndex > toIndex) { 533 throw new IllegalArgumentException("fromIndex must be <= toIndex"); 534 } 535 for(int i = toIndex; i >= fromIndex; i--) { 536 delegate.removeElementAt(i); 537 } 538 fireIntervalRemoved(this, fromIndex, toIndex); 539 } 540 541 /** 542 * Adds all of the elements present in the collection to the list. 543 * 544 * @param c the collection which contains the elements to add 545 * @exception NullPointerException if <code>c</code> is null 546 */ 547 public void addAll(Collection<? extends E> c) { 548 if (c.isEmpty()) { 549 return; 550 } 551 552 int startIndex = getSize(); 553 554 delegate.addAll(c); 555 fireIntervalAdded(this, startIndex, getSize() - 1); 556 } 557 558 /** 559 * Adds all of the elements present in the collection, starting 560 * from the index specified. 561 * 562 * @param index the index from which to start adding elements from 563 * @param c the collection which contains the elements to add 564 * @exception ArrayIndexOutOfBoundsException if <code>index</code> doesn't 565 * fall within the range of number of elements currently held 566 * @exception NullPointerException if <code>c</code> is null 567 */ 568 public void addAll(int index, Collection<? extends E> c) { 569 if (index < 0 || index > getSize()) { 570 throw new ArrayIndexOutOfBoundsException("index out of range: " + 571 index); 572 } 573 if (c.isEmpty()) { 574 return; 575 } 576 577 delegate.addAll(index, c); 578 fireIntervalAdded(this, index, index + c.size() - 1); 579 } 580 }