Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Drag and Drop on Mac OS X

Tags:

java

macos

I am making a Java program, and one way to load files is to drag the file onto the application window (swing). I have code that works in Windows and Linux. It works in OS X, but the 1st file I drag throws an exception, and then the rest work fine.

Here is the code I use to enable DnD.

/*
 * Allow a file to be opened by dragging it onto the window
 */
public void drop(DropTargetDropEvent dtde){
    try {
        // Get the object to be transferred
        Transferable tr = dtde.getTransferable();
        DataFlavor[] flavors = tr.getTransferDataFlavors();

        // If flavors is empty get flavor list from DropTarget
        flavors = (flavors.length == 0) ? dtde.getCurrentDataFlavors() : flavors;

        // Select best data flavor
        DataFlavor flavor = DataFlavor.selectBestTextFlavor(flavors);

        // Flavor will be null on Windows
        // In which case use the 1st available flavor
        flavor = (flavor == null) ? flavors[0] : flavor;

        // Flavors to check
        DataFlavor Linux = new DataFlavor("text/uri-list;class=java.io.Reader");
        DataFlavor Windows = DataFlavor.javaFileListFlavor;

        // On Linux (and OS X) file DnD is a reader
        if(flavor.equals(Linux)) {
            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);

            BufferedReader read = new BufferedReader(flavor.getReaderForText(tr));
            // Remove 'file://' from file name
            String fileName = read.readLine().substring(7).replace("%20"," ");
            // Remove 'localhost' from OS X file names
            if(fileName.substring(0,9).equals("localhost")) {
                fileName = fileName.substring(9);
            }
            read.close();

            dtde.dropComplete(true);
            System.out.println("File Dragged:" + fileName);
            mainWindow.openFile(fileName);
        }
        // On Windows file DnD is a file list
        else if(flavor.equals(Windows)) {
            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
            @SuppressWarnings("unchecked")
            List<File> list = (List<File>)tr.getTransferData(flavor);
            dtde.dropComplete(true);

            if(list.size() == 1) {
                System.out.println("File Dragged: " + list.get(0));
                mainWindow.openFile(list.get(0).toString());
            }
        } else {
            System.err.println("DnD Error");
            dtde.rejectDrop();
        }
    }
    //TODO: OS X Throws ArrayIndexOutOfBoundsException on first DnD
    catch(ArrayIndexOutOfBoundsException e){
        System.err.println("DnD not initalized properly, please try again.");
    } catch(IOException e){
        System.err.println(e.getMessage());
    } catch(UnsupportedFlavorException e){
        System.err.println(e.getMessage());
    } catch (ClassNotFoundException e){
        System.err.println(e.getMessage());
    }
}

For some reason, OS X throws an ArrayIndexOutOfBoundsException on this line:

flavor = (flavor == null) ? flavors[0] : flavor;

After that exception is thrown, if I drag another file onto the window, it works. Why does it throw an exception?

NOTE: mainWindow.openFile() is a function that opens a file. It takes a string parameter (the file name), and the program opens that file.

NOTE 2: This is on OS X 10.6.2 (Snow Leopard).

like image 505
Rocket Hazmat Avatar asked Nov 08 '09 21:11

Rocket Hazmat


1 Answers

I had this problem too but it appears to be fixed with the latest java version:

ray@featuritis:~/projects>java -version
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04-248-10M3025)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01-101, mixed mode)
like image 106
depsypher Avatar answered Nov 15 '22 10:11

depsypher