Reputation: 59
I want to create a DND action from a JList to the OS. My solution for now is to use a TransferHandler. In the method createTransferable I create the Transferable with the files I want to copy.
But now there is my Problem: in some cases I have to download the files from a FTP-Server before I can copy the files. The very heavy download operation runs in a JavaSwingWorker (hidden behind the statement d.download(tmpDir);). Now the system trys to copy files which are not downloaded already.
Now i need a mechanism that allows me to create the transferable after I have downloaded the files. Is there a solution for my problem? Please help me!
Thanks!
Here is my method:
public Transferable createTransferable(JComponent c) {
JList list = (JList) c; // we know it's a JList
List<PictureDecorator> selectedPictures = getSelectedValues(list.getModel());
Vector cpFiles = new Vector();
List<Picture> donePictures = new ArrayList<Picture>();
List<Picture> notDonePictures = new ArrayList<Picture>();
String tmpDir = System.getProperty("java.io.tmpdir");
for(PictureDecorator pd : selectedPictures){
if(pd.getPic().getStatus() == PictureStatus.DONE)
donePictures.add(pd.getPic());
else
notDonePictures.add(pd.getPic());
}
Downloader d = new Downloader(parent, loginInformation, sced, donePictures, order);
d.download(tmpDir);
for(Picture p : donePictures){
cpFiles.add(new File(tmpDir + File.separator + p.getPicture().getName()));
}
for(Picture p : notDonePictures) {
cpFiles.add(p.getPicture());
}
TransferableFile tf = new TransferableFile(cpFiles);
return tf;
}
I need something that initiates the drag procedure then I get the path where the drag goes and then I can download the pictures and copy it to the destination path.
EDIT: Or another formulation: How I can find out the drop destination when I drop into the operating system?
Upvotes: 3
Views: 370
Reputation: 4816
To start the drag you need either a TransferHandler
on the JList
or alternatively a DragSource
in combination with a DragGestureListener
. Below you can see an example for doing that with a JTextField
:
final JTextField textField = new JTextField(50);
DragGestureListener dragListener = new DragGestureListener() {
@Override
public void dragGestureRecognized(DragGestureEvent dge) {
// how the drag cursor should look like
Cursor cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
// the component being dragged
JTextField tf = (JTextField) dge.getComponent();
// Here a Transferable is created directly for a single file name
dge.startDrag(cursor, new TransferableFile(tf.getText()));
}
};
final DragSource ds = new DragSource();
ds.createDefaultDragGestureRecognizer(textField, DnDConstants.ACTION_COPY, dragListener);
You can put the above code inside your window creation procedure.
Your resulting transferable (TransferableFile
in your case) should support the DataFlavor.javaFileListFlavor
and you should return a List
of File
s from the getTransferData(DataFlavor flavor)
method.
I believe this is also the method where the downloading should take place because that's the last point under your control before JVM-OS take over.
Now regarding the SwingWorker
problem you can wait inside the method until the download completes. Perhaps modify your Downloader
class to expose a boolean flag so you would be able to do something like while (!downloader.isDone()) { Thread.sleep(millisToSleep) };
[Edit: I must admit I don't like the idea of keeping the EventDispath thread busy but if this solves your current problem perhaps you can investigate later a more elegant solution]
A little warning: Since you don't have access to the drop location you cannot know how many times the getTransferData
will be called. It is better to take this into account and create a simple cache (a Map
sounds reasonable) with the temp files you have downloaded so far. In case you find the file in the cache you return its corresponding temp file directly and don't download it again.
Hope that helps
Upvotes: 1