JAL-3026 srcjar files for VARNA and log4j
[jalview.git] / srcjar / fr / orsay / lri / varna / components / ReorderableJList.java
diff --git a/srcjar/fr/orsay/lri/varna/components/ReorderableJList.java b/srcjar/fr/orsay/lri/varna/components/ReorderableJList.java
new file mode 100644 (file)
index 0000000..791c451
--- /dev/null
@@ -0,0 +1,219 @@
+package fr.orsay.lri.varna.components;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragGestureRecognizer;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DragSourceDragEvent;
+import java.awt.dnd.DragSourceDropEvent;
+import java.awt.dnd.DragSourceEvent;
+import java.awt.dnd.DragSourceListener;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetEvent;
+import java.awt.dnd.DropTargetListener;
+import java.io.IOException;
+
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.JList;
+
+public class ReorderableJList extends JList 
+implements DragSourceListener, DropTargetListener, DragGestureListener {
+
+static DataFlavor localObjectFlavor;
+static {
+    try {
+        localObjectFlavor =
+            new DataFlavor (DataFlavor.javaJVMLocalObjectMimeType);
+    } catch (ClassNotFoundException cnfe) { cnfe.printStackTrace(); } 
+} 
+static DataFlavor[] supportedFlavors = { localObjectFlavor }; 
+DragSource dragSource; 
+DropTarget dropTarget; 
+int dropTargetIndex; 
+int draggedIndex = -1;
+
+public ReorderableJList () {
+    super();
+    setCellRenderer (new ReorderableListCellRenderer());
+    setModel (new DefaultListModel());
+    dragSource = new DragSource();
+    DragGestureRecognizer dgr =
+        dragSource.createDefaultDragGestureRecognizer (this,
+                                   DnDConstants.ACTION_MOVE,
+                                                       this);
+    dropTarget = new DropTarget (this, this);
+}
+
+// DragGestureListener
+public void dragGestureRecognized (DragGestureEvent dge) {
+    //System.out.println ("dragGestureRecognized");
+    // find object at this x,y
+    Point clickPoint = dge.getDragOrigin();
+    int index = locationToIndex(clickPoint);
+    if (index == -1)
+        return;
+    Object target = getModel().getElementAt(index);
+    Transferable trans = new RJLTransferable (target);
+    draggedIndex = index;
+    dragSource.startDrag (dge,Cursor.getDefaultCursor(),
+                          trans, this);
+}
+// DragSourceListener events
+public void dragDropEnd (DragSourceDropEvent dsde) {
+   //System.out.println ("dragDropEnd()");
+   dropTargetIndex = -1;
+   draggedIndex = -1;
+   repaint();
+}
+public void dragEnter (DragSourceDragEvent dsde) {}
+public void dragExit (DragSourceEvent dse) {}
+public void dragOver (DragSourceDragEvent dsde) {}
+public void dropActionChanged (DragSourceDragEvent dsde) {}
+// DropTargetListener events
+public void dragEnter (DropTargetDragEvent dtde) {
+    //System.out.println ("dragEnter");
+    if (dtde.getSource() != dropTarget)
+        dtde.rejectDrag();
+    else {
+        dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
+        //System.out.println ("accepted dragEnter");
+    }
+}
+public void dragExit (DropTargetEvent dte) {}
+
+public void dropActionChanged (DropTargetDragEvent dtde) {}
+
+public void dragOver (DropTargetDragEvent dtde) { 
+    // figure out which cell it's over, no drag to self    
+    if (dtde.getSource() != dropTarget)
+        dtde.rejectDrag();
+    Point dragPoint = dtde.getLocation();
+    int index = locationToIndex (dragPoint);
+    dropTargetIndex = index;
+    if (dropTargetIndex != -1)
+    {
+       Rectangle r = getCellBounds(dropTargetIndex,dropTargetIndex);
+        if (dragPoint.y > r.y+r.height/2)
+        {
+               dropTargetIndex += 1;           
+        }
+    }
+    //System.out.println(dropTargetIndex);
+    repaint(); 
+}
+
+public void drop (DropTargetDropEvent dtde) {    
+    //System.out.println ("drop()!");    
+    if (dtde.getSource() != dropTarget) {
+        //System.out.println ("rejecting for bad source (" +
+        //                    dtde.getSource().getClass().getName() + ")");        
+        dtde.rejectDrop(); 
+        return;
+    }
+    Point dropPoint = dtde.getLocation();
+    int index = locationToIndex (dropPoint);
+    if (index != -1)
+    {
+       Rectangle r = getCellBounds(index,index);
+        if (dropPoint.y > r.y+r.height/2)
+        {
+               index += 1;             
+        }
+    }
+    
+    //System.out.println ("drop index is " + index);
+    boolean dropped = false;
+    try {
+        if ((index == -1) || (index == draggedIndex)|| (index == draggedIndex+1)) {
+            //System.out.println ("dropped onto self");
+            dtde.rejectDrop();
+            return;
+        }
+        dtde.acceptDrop (DnDConstants.ACTION_MOVE);
+        //System.out.println ("accepted");
+        Object dragged =
+           dtde.getTransferable().getTransferData(localObjectFlavor);
+        // move items - note that indicies for insert will 
+        // change if [removed] source was before target 
+        //System.out.println ("drop " + draggedIndex + " to " + index);
+        boolean sourceBeforeTarget = (draggedIndex < index); 
+        //System.out.println ("source is" +
+        //                    (sourceBeforeTarget ? "" : " not") +
+        //                    " before target");
+        //System.out.println ("insert at " +
+        //                    (sourceBeforeTarget ? index-1 : index));
+         DefaultListModel mod = (DefaultListModel) getModel(); 
+        mod.remove (draggedIndex); 
+        mod.add ((sourceBeforeTarget ? index-1 : index), dragged); 
+        dropped = true;
+    } catch (Exception e) {
+        e.printStackTrace();
+    }
+    dtde.dropComplete (dropped);
+}
+
+private class ReorderableListCellRenderer 
+extends DefaultListCellRenderer { 
+boolean isTargetCell; 
+boolean isLastItem;    
+public ReorderableListCellRenderer() {
+    super();
+}
+public Component getListCellRendererComponent (JList list,
+                                               Object value, 
+                                               int index, 
+                                               boolean isSelected,                                                  boolean hasFocus) {
+    isTargetCell = (index == dropTargetIndex);
+    isLastItem = (index == list.getModel().getSize()-1) && (dropTargetIndex == list.getModel().getSize());
+    boolean showSelected = isSelected;
+    return super.getListCellRendererComponent (list, value, 
+                                               index, showSelected,                                                 
+                                               hasFocus);
+}
+public void paintComponent (Graphics g) {
+    super.paintComponent(g);
+    if (isTargetCell) {
+        g.setColor(Color.black);            
+        g.drawLine (0, 0, getSize().width, 0); 
+    } 
+    if (isLastItem) {
+        g.setColor(Color.black);            
+        g.drawLine (0, getSize().height-1, getSize().width, getSize().height-1); 
+    } 
+ } 
+}
+
+private class RJLTransferable implements Transferable { 
+    Object object; 
+    public RJLTransferable (Object o) {
+        object = o;
+    }
+    public Object getTransferData(DataFlavor df)
+        throws UnsupportedFlavorException, IOException {
+        if (isDataFlavorSupported (df))
+            return object;
+        else
+           throw new UnsupportedFlavorException(df);
+    }
+    public boolean isDataFlavorSupported (DataFlavor df) {
+        return (df.equals (localObjectFlavor));
+    }
+    public DataFlavor[] getTransferDataFlavors () {
+        return supportedFlavors; } 
+}
+
+
+}