X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=srcjar%2Ffr%2Forsay%2Flri%2Fvarna%2Fcomponents%2FReorderableJList.java;fp=srcjar%2Ffr%2Forsay%2Flri%2Fvarna%2Fcomponents%2FReorderableJList.java;h=791c45183adae1d6cf3e1fb7eac33db3e5e2d608;hb=ec8f3cedf60fb1feed6d34de6b49f6bfa78b9dd8;hp=0000000000000000000000000000000000000000;hpb=056dad85a910551cc95e44d451a61f6b8c4dd35d;p=jalview.git diff --git a/srcjar/fr/orsay/lri/varna/components/ReorderableJList.java b/srcjar/fr/orsay/lri/varna/components/ReorderableJList.java new file mode 100644 index 0000000..791c451 --- /dev/null +++ b/srcjar/fr/orsay/lri/varna/components/ReorderableJList.java @@ -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; } +} + + +}