Skip to content

Commit d0802b1

Browse files
authored
Merge pull request #33 from scijava/fix-file-drag-n-drop
Fix drag-n-drop and paste behavior of SwingFileWidget
2 parents c7d104e + 26ab4d8 commit d0802b1

File tree

1 file changed

+55
-6
lines changed

1 file changed

+55
-6
lines changed

src/main/java/org/scijava/ui/swing/widget/SwingFileWidget.java

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import java.awt.datatransfer.DataFlavor;
3434
import java.awt.datatransfer.UnsupportedFlavorException;
35+
import java.awt.dnd.InvalidDnDOperationException;
3536
import java.awt.event.ActionEvent;
3637
import java.awt.event.ActionListener;
3738
import java.io.File;
@@ -287,6 +288,24 @@ public static List<File> getFiles(
287288
}
288289
}
289290

291+
/**
292+
* Gets the String content of the current transfer support
293+
*
294+
* @param support
295+
* The paste (or drag and drop) operation from which text should
296+
* be extracted.
297+
*
298+
* @return The pasted (or dropped) text
299+
*/
300+
public static String getText(final TransferHandler.TransferSupport support) {
301+
try {
302+
return (String) support.getTransferable().getTransferData(DataFlavor.stringFlavor);
303+
} catch (UnsupportedFlavorException | IOException exc) {
304+
return "";
305+
}
306+
307+
}
308+
290309
/**
291310
* Filters the given list of files according to the specified
292311
* {@link FileFilter}.
@@ -314,18 +333,48 @@ public FileTransferHandler(final String style) {
314333
@Override
315334
public boolean canImport(final TransferHandler.TransferSupport support) {
316335
if (!hasFiles(support)) return false;
317-
final List<File> allFiles = getFiles(support);
318-
if (allFiles == null || allFiles.size() != 1) return false;
319336

320-
final FileFilter filter = SwingFileWidget.createFileFilter(style);
321-
final List<File> files = SwingFileWidget.filterFiles(allFiles, filter);
322-
return files.size() == 1;
337+
// We wish to test the content of the transfer data and
338+
// determine if they are (a) files and (b) files we are
339+
// actually interested in processing. So we need to call
340+
// getTransferData() so that we can inspect the file names.
341+
// Unfortunately, this will not always work.
342+
// Under Windows, the Transferable instance
343+
// will have transfer data ONLY while the mouse button is
344+
// depressed. However, when the user releases the mouse
345+
// button, this method will be called one last time. And when
346+
// when this method attempts to getTransferData, Java will throw
347+
// an InvalidDnDOperationException. Since we know that the
348+
// exception is coming, we simply catch it and ignore it.
349+
// See:
350+
// https://coderanch.com/t/664525/java/Invalid-Drag-Drop-Exception
351+
try {
352+
final List<File> allFiles = getFiles(support);
353+
if (allFiles == null || allFiles.size() != 1)
354+
return false;
355+
356+
final FileFilter filter = SwingFileWidget
357+
.createFileFilter(style);
358+
final List<File> files = SwingFileWidget.filterFiles(allFiles,
359+
filter);
360+
return files.size() == 1;
361+
} catch (InvalidDnDOperationException exc) {
362+
return true;
363+
}
323364
}
324365

325366
@Override
326367
public boolean importData(TransferHandler.TransferSupport support) {
327368
final List<File> files = getFiles(support);
328-
if (files == null || files.size() != 1) return false;
369+
if (files == null) {
370+
String text = getText(support);
371+
if (text.equals(""))
372+
return false;
373+
// TODO check if text matches filter/style
374+
((JTextField) support.getComponent()).setText(text);
375+
return true;
376+
}
377+
if (files.size() != 1) return false;
329378

330379
final File file = files.get(0);
331380
((JTextField) support.getComponent()).setText(file.getAbsolutePath());

0 commit comments

Comments
 (0)