/*
 *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 Manchester as a Pfizer post-doctoral 
 * Research Fellow. 
 *
 * The initial code base is copyright by Pfizer, or the University
 * of Manchester. 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.awt.event.MouseEvent;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.basic.BasicListUI;


/**
 * SwappingListBasicUI.java
 *
 * This class enables dragging of list items around something like
 * XMMS's playlist. 
 * Because it has to modify the list it must perform a dodgy cast, to
 * some form of modifiable ListModel. In this case it assumes that the
 * list extends DefaultListModel. (PENDING:- PL) I should include some
 * checking for this when ever the UI is associated with a JList or
 * whenever the ListModel is changed, which would give me fail fast
 * behaviour. 
 *
 * Created: Tue Oct  3 18:40:07 2000
 *
 * @author Phillip Lord
 * @version $Id: SwappingListBasicUI.java,v 1.3 2001/04/11 17:04:42 lord Exp $
 */

public class SwappingListBasicUI extends BasicListUI
{
  protected MouseInputListener createMouseInputListener()
  {
    return new SwappingMouseInputHandler();
  }
  
  protected int convertYToRow( int y )
  {
    return super.convertYToRow( y );
  }
  
  protected JList getJList()
  {
    return list;
  }
  
  public class SwappingMouseInputHandler extends MouseInputHandler
  {
    private int indexOfElementBeingDragged = -1;
    
    public void mousePressed( MouseEvent event )
    {
      // call the super class to get the selection stuff all working
      // correctly.
      super.mousePressed( event );
      
      if( SwingUtilities.isLeftMouseButton( event ) ){
	// and keep a record of the value that we first pressed on so
	// that we can drag it.
	int row = convertYToRow( event.getY() );
	if( row != -1 ){
	  indexOfElementBeingDragged = row;
	}
      }
      else{
	// clear the drag
	indexOfElementBeingDragged = -1;
      }
    }
    
    public void mouseDragged( MouseEvent e )
    {
      if( SwingUtilities.isLeftMouseButton( e ) ){
	int row = convertYToRow( e.getY() );
	
	if( row != -1 && row != indexOfElementBeingDragged ){
	  int max = Math.max( row,indexOfElementBeingDragged );
	  int min = Math.min( row, indexOfElementBeingDragged );
	  
	  swap( max, min );
	  
	  // now remember where the element being dragged is 
	  indexOfElementBeingDragged = row;
	}
      }
    }
    
    protected void swap( int max, int min )
    {
      JList list = getJList();
      
      // here is the dodgy cast
      DefaultListModel model = (DefaultListModel)list.getModel();
      
      // this lots just swaps the stuff over
      Object upper = model.remove( max );
      Object lower = model.getElementAt( min );
      model.insertElementAt( lower, max );
      model.remove( min );
      model.insertElementAt( upper, min );
    }
  }
} // SwappingListBasicUI



/*
 * ChangeLog
 * $Log: SwappingListBasicUI.java,v $
 * Revision 1.3  2001/04/11 17:04:42  lord
 * Added License agreements to all code
 *
 * Revision 1.2  2000/10/12 11:30:14  lord
 * Changes getJlist from private to protected
 *
 * Revision 1.1  2000/10/11 15:35:03  lord
 * Initial checkin
 *
 */
