Reputation: 1899
So I have written a TransferHandler for my application (along the example from Oracle site) but when I am trying to move the data it is not moving. All it is doing is copying the data at index ( n-1 i.e if I am moving and item to n location) to index n. Could you please check what is wrong, though I have tried many options but none of them is working for me.
import javax.swing.TransferHandler;
import javax.swing.*;
import java.awt.datatransfer.*;
public class ListTransferHandler extends TransferHandler {
private int[] indices = null;
private int addIndex = -1; //Location where items were added
private int addCount = 0; //Number of items added.
public boolean canImport(TransferHandler.TransferSupport info) {
// Check for String flavor
if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
return false;
}
return true;
}
protected Transferable createTransferable(JComponent c) {
return new StringSelection(exportString(c));
}
public int getSourceActions(JComponent c) {
return TransferHandler.MOVE;
}
public boolean importData(TransferHandler.TransferSupport info) {
if (!info.isDrop()) {
return false;
}
JList list = (JList)info.getComponent();
DefaultListModel listModel = (DefaultListModel)list.getModel();
JList.DropLocation dl = (JList.DropLocation)info.getDropLocation();
int index = dl.getIndex();
boolean insert = dl.isInsert();
// Get the string that is being dropped.
Transferable t = info.getTransferable();
String data;
try {
data = (String)t.getTransferData(DataFlavor.stringFlavor);
}
catch (Exception e) { return false; }
// Perform the actual import.
if (insert) {
listModel.add(index, data);
} else {
listModel.set(index, data);
}
return true;
}
protected void exportDone(JComponent c, Transferable data, int action) {
cleanup(c, action == TransferHandler.MOVE);
}
//Bundle up the selected items in the list
//as a single string, for export.
protected String exportString(JComponent c) {
JList list = (JList)c;
indices = list.getSelectedIndices();
Object[] values = list.getSelectedValues();
StringBuffer buff = new StringBuffer();
for (int i = 0; i < values.length; i++) {
Object val = values[i];
buff.append(val == null ? "" : val.toString());
if (i != values.length - 1) {
buff.append("\n");
}
}
return buff.toString();
}
//Take the incoming string and wherever there is a
//newline, break it into a separate item in the list.
protected void importString(JComponent c, String str) {
JList target = (JList)c;
DefaultListModel listModel = (DefaultListModel)target.getModel();
int index = target.getSelectedIndex();
//Prevent the user from dropping data back on itself.
//For example, if the user is moving items #4,#5,#6 and #7 and
//attempts to insert the items after item #5, this would
//be problematic when removing the original items.
//So this is not allowed.
if (indices != null && index >= indices[0] - 1 &&
index <= indices[indices.length - 1]) {
indices = null;
return;
}
int max = listModel.getSize();
if (index < 0) {
index = max;
} else {
index++;
if (index > max) {
index = max;
}
}
addIndex = index;
String[] values = str.split("\n");
addCount = values.length;
for (int i = 0; i < values.length; i++) {
listModel.add(index++, values[i]);
}
}
//If the remove argument is true, the drop has been
//successful and it's time to remove the selected items
//from the list. If the remove argument is false, it
//was a Copy operation and the original list is left
//intact.
protected void cleanup(JComponent c, boolean remove) {
if (remove && indices != null) {
JList source = (JList)c;
DefaultListModel model = (DefaultListModel)source.getModel();
//If we are moving items around in the same list, we
//need to adjust the indices accordingly, since those
//after the insertion point have moved.
if (addCount > 0) {
for (int i = 0; i < indices.length; i++) {
if (indices[i] > addIndex) {
indices[i] += addCount;
}
}
}
for (int i = indices.length - 1; i >= 0; i--) {
model.remove(indices[i]);
}
}
indices = null;
addCount = 0;
addIndex = -1;
}
}
Upvotes: 2
Views: 1539
Reputation: 347204
You need to "remove" the data from the source once the export has been completed successfully.
In order to do this, you need to override the TransferHandler.exportDone
method.
protected void exportDone(JComponent source, Transferable data, int action)
Invoked after data has been exported. This method should remove the data that was transferred if the action was MOVE.
This method is implemented to do nothing since MOVE is not a supported action of this implementation (getSourceActions does not include MOVE).
Basically, from there you need to check the action
type and make sure the target component has accepted the MOVE
and not simply COPY
'ed it and remove the element from the source list.
Upvotes: 2