/*
 *This library is free software; you can redistribute it and/or
 *modify it under the terms of the GNU Lesser General Public
 *License as published by the Free Software Foundation; either
 *version 2.1 of the License, or (at your option) any later version.
 *
 *This library is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *Lesser General Public License for more details.
 *
 *You should have received a copy of the GNU Lesser General Public
 *License along with this library; if not, write to the Free Software
 *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* 
 * This software was written by Phillip Lord (p.lord@hgmp.mrc.ac.uk)
 * whilst at the University of Middlesex as a reseach fellow, on a
 * project funded by the Birth Defects Foundation.
 *
 * The initial code base is copyright by the University of Middlesex,
 * or the Birth Defects Foundation, or even possibly by me.
 * Modifications to the initial code base are copyright
 * of their respective authors, or their employers as appropriate. 
 * Authorship of the modifications may be determined from the ChangeLog
 * placed at the end of this file
 */
package uk.ac.man.bioinf.gui.misc; // Package name inserted by JPack

import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
import javax.swing.AbstractListModel;

/**
 * ChunkyListModel.java
 *
 * This is a small extension to the list model class. It allows the addition
 * of several elements at once, with only one fireIntervalAdded event occuring. 
 * The reason for this is essentially performance. The DefaultListModel appears
 * to cause a huge amount of repainting whilst it is being loaded with data, which
 * means that it gets a lot slower to add elements when they already are. Whilst there
 * are probably better ways to solve this problem, the simplest would appear to be 
 * add the elements in chunks. 
 *
 * Since I have written this code I have found various other ways
 * around the repaint problem. However this code is still pretty
 * useful because its got some nice convenience methods for adding and
 * removing many elements at once.
 *
 * The class name is still pretty terrible though.
 *
 * <P> 
 * Created: Tue Nov 17 13:43:56 1998
 * <P> 
 * Compliant: 1.0
 * 
 * @author Phillip Lord
 * @version $Id: ChunkyListModel.java,v 1.4 2001/04/11 17:04:42 lord Exp $
 */
public class ChunkyListModel extends AbstractListModel 
{
  private Vector delegate = new Vector();
  
  public ChunkyListModel() 
  {
    super();
  }


  /**
   * This method takes a collection, adds all the elements, 
   * then fires an event. This method isnt thread safe, call
   * from the event thread only
   * @param c the collection to be added
   */
  public void addAll( Collection collection )
  {
    addAll( collection.toArray() );
  }
  
  /**
   * Add all the elements of this array to the list model
   * @param object the array
   */
  public void addAll( Object[] object )
  {
    //The start and stop indexes
    int startIndex = delegate.size();
    int stopIndex = startIndex + object.length;
    
    //Add them all
    for ( int i = 0; i < object.length; i++ ){
	  delegate.addElement( object[ i ] );
    }
    
    //Inform everything its happened
    fireIntervalAdded( this, startIndex, stopIndex );
  }
  
  /**
   * Add all the elements of this vector to the list model
   * @param vector the vector
   */
  public void addAll( Vector vector )
  {
    addAll( vector.toArray() );
  }

  public List toList()
  {
    return delegate;
  }
  
  Collection toCollection()
  {
    return delegate;
  }
  
  Vector toVector()
  {
    return delegate;
  }
  
  /**
   * Removes all the elements of this array from the list modely
   * @param object the array
   */
  public void removeAll( Object[] object )
  {
    for ( int i = 0; i < object.length; i ++ ){
      removeElement( object[ i ] );
    }
    fireIntervalRemoved( this, 0, object.length );
  }
  
  public void removeAll( Vector vector )
  {
    removeAll( vector.toArray() );
  }
  
  public void removeAll( Collection collection )
  {
    removeAll( collection.toArray() );
  }
  

  
  /**
   * Everything that follows this is just a straight copy from 
   * the default list model
   * @return the size
   */
  public int getSize() {
    return delegate.size();
  }
  
  public Object getElementAt(int index) {
    return delegate.elementAt(index);
  }
  
  public void copyInto(Object anArray[]) {
    delegate.copyInto(anArray);
  }
  
  public void trimToSize() {
    delegate.trimToSize();
  }
  
  public void ensureCapacity(int minCapacity) {
    delegate.ensureCapacity(minCapacity);
  }
  
  public void setSize(int newSize) {
    int oldSize = delegate.size();
    delegate.setSize(newSize);
    if (oldSize > newSize) {
      fireIntervalRemoved(this, newSize, oldSize-1);
    }
    else if (oldSize < newSize) {
      fireIntervalAdded(this, oldSize, newSize-1);
    }
  }
  
  public int capacity() {
    return delegate.capacity();
  }
  
  public int size() {
    return delegate.size();
  }
  
  public boolean isEmpty() {
    return delegate.isEmpty();
  }
  
  public Enumeration elements() {
    return delegate.elements();
  }
  
  public boolean contains(Object elem) {
    return delegate.contains(elem);
  }
  
  public int indexOf(Object elem) {
    return delegate.indexOf(elem);
  }
  
  public int indexOf(Object elem, int index) {
    return delegate.indexOf(elem, index);
  }
  
  public int lastIndexOf(Object elem) {
    return delegate.lastIndexOf(elem);
  }
  
  public int lastIndexOf(Object elem, int index) {
    return delegate.lastIndexOf(elem, index);
  }
  
  public Object elementAt(int index) {
    return delegate.elementAt(index);
  }
  
  public Object firstElement() {
    return delegate.firstElement();
  }
  
  public Object lastElement() {
    return delegate.lastElement();
  }
  
  public void setElementAt(Object obj, int index) {
    delegate.setElementAt(obj, index);
    fireContentsChanged(this, index, index);
  }
  
  public void removeElementAt(int index) {
    delegate.removeElementAt(index);
    fireIntervalRemoved(this, index, index);
  }
  
  public void insertElementAt(Object obj, int index) {
    delegate.insertElementAt(obj, index);
    fireIntervalAdded(this, index, index);
  }
  
  public void addElement(Object obj) {
    int index = delegate.size();
    delegate.addElement(obj);
    fireIntervalAdded(this, index, index);
  }
  
  public boolean removeElement(Object obj) {
    int index = indexOf(obj);
    boolean rv = delegate.removeElement(obj);
    if (index > 0) {
      fireIntervalRemoved(this, index, index);
    }
    return rv;
  }
  
  
  public void removeAllElements() {
    int index1 = delegate.size()-1;
    delegate.removeAllElements();
    if (index1 >= 0) {
      fireIntervalRemoved(this, 0, index1);
    }
  }
  
  
  public String toString() {
    return delegate.toString();
  }
  
  /* The remaining methods are included for compatibility with the
   * JDK1.2 Vector class.
   */
  
  public Object[] toArray() {
    Object[] rv = new Object[delegate.size()];
    delegate.copyInto(rv);
    return rv;
  }
  
  public Object get(int index) {
    return delegate.elementAt(index);
  }
  
  public Object set(int index, Object element) {
    Object rv = delegate.elementAt(index);
    delegate.setElementAt(element, index);
    fireContentsChanged(this, index, index);
    return rv;
  }
  
  public void add(int index, Object element) {
    delegate.insertElementAt(element, index);
    fireIntervalAdded(this, index, index);
  }
  
  public Object remove(int index) {
    Object rv = delegate.elementAt(index);
    delegate.removeElementAt(index);
    fireIntervalRemoved(this, index, index);
    return rv;
  }
  
  public void clear() {
    int index1 = delegate.size()-1;
    delegate.removeAllElements();
    if (index1 >= 0) {
      fireIntervalRemoved(this, 0, index1);
    }
  }
  
  public void removeRange(int fromIndex, int toIndex) {
    for(int i = toIndex; i >= fromIndex; i--) {
      delegate.removeElementAt(i);
    }
    fireIntervalRemoved(this, fromIndex, toIndex);
  }
  

} // ChunkyListModel



/*
 * ChangeLog
 * $Log: ChunkyListModel.java,v $
 * Revision 1.4  2001/04/11 17:04:42  lord
 * Added License agreements to all code
 *
 * Revision 1.3  2000/12/05 15:54:37  lord
 * Import rationalisation
 *
 * Revision 1.2  2000/10/11 15:41:09  lord
 * import sorting
 *
 * Revision 1.1  2000/06/05 14:21:25  lord
 * Initial checkin in bioinf package
 *
 * Revision 1.3  1999/10/14 14:00:52  phillip2
 * Changed packages and a few other bits and bobs
 *
 * Revision 1.3  1999-10-12 14:47:31+01  phillip2
 * Outdated (renamed to 'D:\Home\rcs\D\Home\java\sources\photofit\editor\gui\ChunkyListModel.java,v').
 *
 * Revision 1.3  1999-10-04 16:22:21+01  phillip2
 * Outdated (renamed to 'D:\Home\rcs\D\Home\java\sources\photofit\editor\gui\ChunkyListModel.java,v').
 *
 * Revision 1.2  1999-05-17 12:37:20+01  phillip2
 * Removed * from imports
 *
 * Revision 1.1  1999-02-02 16:04:00+00  phillip2
 * Initial revision
 *
 */
