001/*
002 *  $Source: v:/cvsroot/open/projects/WebARTS/ca/bc/webarts/widgets/dnd/DnDList.java,v $
003 *  $Name:  $
004 *  $Revision: 1.1 $
005 *  $Date: 2005-04-10 11:53:16 -0700 (Sun, 10 Apr 2005) $
006 *  $Locker:  $
007 */
008/*
009 *  Copyright (C) 2001 WebARTS Design, North Vancouver Canada
010 *  http://www..webarts.bc.ca
011 *
012 *  This program is free software; you can redistribute it and/or modify
013 *  it under the terms of the GNU General Public License as published by
014 *  the Free Software Foundation; either version 2 of the License, or
015 *  (at your option) any later version.
016 *
017 *  This program is distributed in the hope that it will be useful,
018 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
019 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
020 *  GNU General Public License for more details.
021 *
022 *  You should have received a copy of the GNU General Public License
023 *  along with this program; if not, write to the Free Software
024 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
025 */
026package ca.bc.webarts.widgets.dnd;
027
028/**
029 * An extension of {@link javax.swing.JList} that supports drag and drop
030 * to rearrange its contents and to move objects in and out of the list.
031 * The objects in the list will be passed either as a String by calling
032 * the object's <tt>toString()</tt> object, or if your drag and drop target
033 * accepts the {@link TransferableObject#DATA_FLAVOR} data flavor then
034 * the actual object will be passed.
035 *
036 * <p>I'm releasing this code into the Public Domain. Enjoy.
037 * </p>
038 * <p><em>Original author: Robert Harder, rharder@usa.net</em></p>
039 *
040 * @author  Robert Harder
041 * @author  rharder@usa.net
042 * @version 1.1
043 */
044public class DnDList
045extends javax.swing.JList
046implements  java.awt.dnd.DropTargetListener,
047            java.awt.dnd.DragSourceListener,
048            java.awt.dnd.DragGestureListener
049{
050
051    private java.awt.dnd.DropTarget dropTarget = null;
052
053    private java.awt.dnd.DragSource dragSource = null;
054
055    private int sourceIndex = -1;
056    private int dropIndex   = -1;
057    private Object sourceObject;
058
059
060    /**
061     * Constructs a default {@link DnDList} using a
062     * {@link javax.swing.DefaultListModel}.
063     *
064     * @since 1.1
065     */
066    public DnDList()
067    {
068        super( new javax.swing.DefaultListModel() );
069        initComponents();
070    }   // end constructor
071
072
073
074    /**
075     * Constructs a {@link DnDList} using the
076     * passed list model that must be extended from
077     * {@link javax.swing.DefaultListModel}.
078     *
079     * @param model The model to use
080     * @since 1.1
081     */
082    public DnDList( javax.swing.DefaultListModel model )
083    {   super( model );
084        initComponents();
085    }   // end constructor
086
087
088
089    /**
090     * Constructs a {@link DnDList} by
091     * filling in a {@link javax.swing.DefaultListModel}
092     * with the passed array of objects.
093     *
094     * @param data The data from which to construct a list
095     * @since 1.1
096     */
097    public DnDList( Object[] data )
098    {   this();
099        ((javax.swing.DefaultListModel)getModel()).copyInto( data );
100    }   // end constructor
101
102
103
104
105    /**
106     * Constructs a {@link DnDList} by
107     * filling in a {@link javax.swing.DefaultListModel}
108     * with the passed {@link java.util.Vector} of objects.
109     *
110     * @param data The data from which to construct a list
111     * @since 1.1
112     */
113    public DnDList( java.util.Vector data )
114    {   this();
115        ((javax.swing.DefaultListModel)getModel()).copyInto( data.toArray() );
116    }   // end constructor
117
118
119
120    private void initComponents()
121    {
122        dropTarget = new java.awt.dnd.DropTarget (this, this);
123        dragSource = new java.awt.dnd.DragSource();
124        dragSource.createDefaultDragGestureRecognizer( this, java.awt.dnd.DnDConstants.ACTION_MOVE, this);
125    }   // end initComponents
126
127
128/* ********  D R A G   G E S T U R E   L I S T E N E R   M E T H O D S  ******** */
129
130
131
132
133    public void dragGestureRecognized( java.awt.dnd.DragGestureEvent event)
134    {   //System.out.println( "DragGestureListener.dragGestureRecognized" );
135        final Object selected = getSelectedValue();
136        if ( selected != null )
137        {
138            sourceIndex = getSelectedIndex();
139            java.awt.datatransfer.Transferable transfer = new TransferableObject( new TransferableObject.Fetcher()
140            {   /**
141                 * This will be called when the transfer data is requested at the very end.
142                 * At this point we can remove the object from its original place in the list.
143                 */
144                public Object getObject()
145                {
146                    ((javax.swing.DefaultListModel)getModel()).remove( sourceIndex );
147                    return selected;
148                }   // end getObject
149            }); // end fetcher
150
151            // as the name suggests, starts the dragging
152            dragSource.startDrag (event, java.awt.dnd.DragSource.DefaultLinkDrop, transfer, this);
153        }
154        else
155        {
156            //System.out.println( "nothing was selected");
157        }
158    }   // end dragGestureRecognized
159
160
161/* ********  D R A G   S O U R C E   L I S T E N E R   M E T H O D S  ******** */
162
163
164    public void dragDropEnd( java.awt.dnd.DragSourceDropEvent evt )
165    {   //System.out.println( "DragSourceListener.dragDropEnd" );
166    }   // end dragDropEnd
167
168
169    public void dragEnter( java.awt.dnd.DragSourceDragEvent evt )
170    {   //System.out.println( "DragSourceListener.dragEnter" );
171    }   // end dragEnter
172
173
174    public void dragExit( java.awt.dnd.DragSourceEvent evt )
175    {   //System.out.println( "DragSourceListener.dragExit" );
176    }   // end dragExit
177
178
179    public void dragOver( java.awt.dnd.DragSourceDragEvent evt )
180    {   //System.out.println( "DragSourceListener.dragOver" );
181    }   // end dragOver
182
183
184    public void dropActionChanged( java.awt.dnd.DragSourceDragEvent evt )
185    {   //System.out.println( "DragSourceListener.dropActionChanged" );
186    }   // end dropActionChanged
187
188
189
190/* ********  D R O P   T A R G E T   L I S T E N E R   M E T H O D S  ******** */
191
192
193
194    public void dragEnter( java.awt.dnd.DropTargetDragEvent evt )
195    {   //System.out.println( "DropTargetListener.dragEnter" );
196        evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_MOVE);
197    }   // end dragEnter
198
199    public void dragExit( java.awt.dnd.DropTargetEvent evt )
200    {   //System.out.println( "DropTargetListener.dragExit" );
201    }   // end dragExit
202
203    public void dragOver( java.awt.dnd.DropTargetDragEvent evt )
204    {   //System.out.println( "DropTargetListener.dragOver" );
205    }   // end dragOver
206
207    public void dropActionChanged( java.awt.dnd.DropTargetDragEvent evt )
208    {   //System.out.println( "DropTargetListener.dropActionChanged" );
209        evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_MOVE);
210    }   // end dropActionChanged
211
212
213
214    public void drop( java.awt.dnd.DropTargetDropEvent evt )
215    {   //System.out.println( "DropTargetListener.drop" );
216        java.awt.datatransfer.Transferable transferable = evt.getTransferable();
217
218        // If it's our native TransferableObject, use that
219        if( transferable.isDataFlavorSupported( TransferableObject.DATA_FLAVOR ) )
220        {
221            evt.acceptDrop( java.awt.dnd.DnDConstants.ACTION_MOVE );
222            Object obj = null;
223            try
224            {
225                obj = transferable.getTransferData( TransferableObject.DATA_FLAVOR );
226            }   // end try
227            catch( java.awt.datatransfer.UnsupportedFlavorException e )
228            {   e.printStackTrace();
229            }   // end catch
230            catch( java.io.IOException e )
231            {   e.printStackTrace();
232            }   // end catch
233
234            if( obj != null )
235            {
236                // See where in the list we dropped the element.
237                int dropIndex = locationToIndex( evt.getLocation() );
238                javax.swing.DefaultListModel model = (javax.swing.DefaultListModel)getModel();
239
240                if( dropIndex < 0 )
241                    model.addElement( obj );
242
243                // Else is it moving down the list?
244                else if( sourceIndex >= 0 && dropIndex > sourceIndex )
245                    model.add( dropIndex-1, obj );
246                else
247                    model.add( dropIndex, obj );
248
249            }   // end if: we got the object
250
251            // Else there was a problem getting the object
252            else
253            {
254                evt.rejectDrop();
255            }   // end else: can't get the object
256        }   // end if: it's a native TransferableObject
257
258        // Else we can't handle this
259        else evt.rejectDrop();
260    }   // end drop
261
262
263
264}   // end class DnDList
265