I've tried to implement a drag and drop action of attachments in an email client, and found that the Sun's implementation of DnD makes it impossible to mimic native applications drag and drop actions. The DnD framework does not support creating files lazily. This is a shortcoming that makes it very hard to create feature-rich java clients that can compete with native clients. This is not only true for email clients, its for most clients that work with large files over the network, ex. webbrowsers, FTPs, and others.
The problem comes from the fact that the files must exists locally before the DnD of files can begin.
Note that this is about DnD a file outside the java application!
In the email client the attachments lies within the email(s), and needs to be extracted before they can be copied to the correct location. For performance reasons I dont want to extract all attachments to the disk when the user opens an email with attachments. Neither do I want to extract the attachment during the user's DnD operation. I would like to make the copy/extraction when the DnD has been completed. This is also true for FTP clients as well, for instance if the UI displays the files on the remote server and the user wants to download it to the desktop, preferably he/she should drag the file from the file list to the dekstop.
The only way of copying (or moving) a File through DnD is to create a Transferable object that supports the DataFlavor.javaFileListFlavor. This transferable should return a List of files that are to be copied/moved to the target location. When the DnD action is completed the actual copying/moving of the file is handled deep down within the Suns own code, and I havent found the place to see how its done. But the problem is that the Files must exists locally before the DnD starts, ie before the getTransferData() or the exportDone() methods are called. This I cannot do, since I dont want to extract the attachment until the DnD is complete. (performance issues) There is no way of finding out the target file from the current DnD action., ie it is impossible to make the copying yourself.
My first idea was to create an empty dummy file on the disk, and use this as the source File to be dragged around. Then when the DnD is completed, I would extract the attachment from the email and make the copy manually. Doing it this way, Im sure that
- theres no unecessary extraction,
- the DnD action is not hindered by sharing CPU with the extraction of the file itself
- the user doesnt have to wait until he has choosen where to put the file
- the extraction is done according to the API for the email client.
There are four methods that need to be overloaded in order to get a TransferHandler to work:
- getSourceAction() - return which actions the transfer handler supports, ie copy/move
- createTransferable() - returns a Transferable object that is sent around to the other components that supports DnD actions.
- canImport() - if the current component can import a certain type of data flavors
- exportDone() - is called when the DnD action is finished, remove those objects that has been moved
The Transferable interface has these methods.
- getTransferDataFlavors() - return which data flavors that this supports, in my case the javaFileListFlavor flavor
- isDataFlavorSupported() - return if the transferable understands one type of data flavor
- getTransferData() - return the actual data that is to be DnD'ed, in my case the list of Files
Ive found out that the actual Copying of the files is done before the exportDone() method and after the getTransferData(), which is not suprising since the actual copying is done by the DnD framework. But the exportDone() method has no way of telling what the target was, and therefore makes it impossible to make the copy yourself, or start the download to the location.
So, as far as I can see, there is no solution or workaround for this problem, and that it will be virtually impossible to create applications that can compete with native programs. If someone haves a solution or workaround for this problem, it would be greatly appreciated to get that.
But for now, I think the default implementation of Sun's DnD of Files is nice, but it lacks this important feature that hinders the usability.
SUN bug report - http://developer.java.sun.com/developer/bugParade/bugs/4808793.html - Bug # 4808793