package com.revolsys.swing.dnd.transferhandler; import java.awt.Cursor; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.DragSource; import javax.activation.DataHandler; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.ListModel; import javax.swing.ListSelectionModel; import javax.swing.TransferHandler; import com.revolsys.logging.Logs; import com.revolsys.util.Reorderable; public class ListReorderableTransferHandler extends TransferHandler { private static final long serialVersionUID = 1L; private final JList list; private final DataFlavor localObjectFlavor = new DataFlavor(int[].class, "Integer[]"); private final String mimeType = this.localObjectFlavor.getMimeType(); public ListReorderableTransferHandler(final JList list) { this.list = list; } @Override public boolean canImport(final TransferHandler.TransferSupport info) { if (info.getComponent() == this.list) { if (info.isDrop()) { if (info.isDataFlavorSupported(this.localObjectFlavor)) { this.list.setCursor(DragSource.DefaultMoveDrop); return true; } } } this.list.setCursor(DragSource.DefaultMoveNoDrop); return false; } @Override protected Transferable createTransferable(final JComponent c) { assert c == this.list; final int[] selectedRows = this.list.getSelectedIndices(); if (c == this.list) { return new DataHandler(selectedRows, this.mimeType); } else { return null; } } @Override protected void exportDone(final JComponent c, final Transferable t, final int action) { if (action == TransferHandler.MOVE) { this.list.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } @Override public int getSourceActions(final JComponent c) { return TransferHandler.COPY_OR_MOVE; } @Override public boolean importData(final TransferHandler.TransferSupport info) { final JList target = (JList)info.getComponent(); final JList.DropLocation dropLocation = (JList.DropLocation)info.getDropLocation(); int dropIndex = dropLocation.getIndex(); final ListModel model = this.list.getModel(); final int max = model.getSize(); if (dropIndex < 0 || dropIndex > max) { dropIndex = max; } target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); try { final Transferable transferable = info.getTransferable(); final int[] indices = (int[])transferable.getTransferData(this.localObjectFlavor); if (indices.length > 0) { final Reorderable reorderable = (Reorderable)model; int currentIndex = dropIndex; int count = 0; for (int index : indices) { if (count > 0) { if (currentIndex > index) { index -= count; } } count++; if (index == currentIndex) { currentIndex++; } else { reorderable.reorder(index, currentIndex); if (index > currentIndex) { currentIndex++; } } } final ListSelectionModel selectionModel = target.getSelectionModel(); selectionModel.clearSelection(); selectionModel.addSelectionInterval(currentIndex - indices.length, currentIndex - 1); return true; } } catch (final Throwable e) { Logs.error(this, "Unexpected error", e); } return false; } }