Ned Twigg
Ned Twigg

Reputation: 2224

SWT Drag to Explorer (Windows) or Finder (OS X)

I've got an SWT application with a bunch of graphical elements. I'd like for the user to be able to drag an element to their Desktop / Windows Explorer / OS X Finder. When they drop the element, I need the path that they dropped it to, so that I can create a file in that location which represents the element.

I don't think I can use a FileTransfer, because there is no source file. There is a source object which can create a file, but only once it knows where to put it.

Inlined below is a simple example of what I'm trying to achieve, there is a text box with a label to drag from. If the user drags to some folder or file, I'd like to get the path that they dragged to. If they dragged to a file, I'd like to replace the contents of that file with whatever is in the text box. If they dragged to a folder, I'd like to create a file called "TestFile" with the contents of whatever is in the text box.

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class DesktopDragExample {

public static void main(String[] args) {
    // put together the SWT main loop
    final Display display = Display.getDefault();
    display.syncExec(new Runnable() {
        @Override
        public void run() {
            Shell shell = new Shell(display, SWT.SHELL_TRIM);
            initializeGui(shell);

            //open the shell
            shell.open();

            //run the event loop
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
        }
    });
}

// create the gui
private static void initializeGui(Composite parent) {
    GridLayout layout = new GridLayout(2, false);
    parent.setLayout(layout);

    // make the instructions label
    Label infoLbl = new Label(parent, SWT.WRAP);
    GridData gd = new GridData();
    gd.grabExcessHorizontalSpace = true;
    gd.horizontalAlignment = SWT.FILL;
    gd.horizontalSpan = 2;
    infoLbl.setLayoutData(gd);
    infoLbl.setText(
            "You should be able to drag to the desktop, Windows Explorer, or OS X Finder.\n" +
            "If you drag to a file, it will replace the contents of that file with the contents of the text box.\n" +
            "If you drag to a folder, it will create a file named 'TestFile' whose contents are whatever is in the text box.");

    // make the text element
    final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
    gd = new GridData();
    gd.grabExcessHorizontalSpace = true;
    gd.horizontalAlignment = SWT.FILL;
    text.setLayoutData(gd);

    // make the label element
    Label label = new Label(parent, SWT.NONE);
    label.setText("Drag me");

    // listener for drags
    DragSourceListener dragListener = new DragSourceListener() {
        @Override
        public void dragStart(DragSourceEvent e) {
            e.detail = DND.DROP_COPY;
        }

        @Override
        public void dragFinished(DragSourceEvent e) {
            System.out.println("--dragFinished--");
            System.out.println("e.data=" + e.data);
        }

        @Override
        public void dragSetData(DragSourceEvent e) {
            System.out.println("--dragSetData--");
            System.out.println("e.data=" + e.data);
        }
    };


    // the DragSource
    DragSource dragSource = new DragSource(label, DND.DROP_COPY);
    dragSource.setTransfer(new Transfer[]{FileTransfer.getInstance()});
    dragSource.addDragListener(dragListener);
}

private static void draggedTo(String path, String textBoxContents) {
    System.out.println("Dragged the contents '" + textBoxContents + "' to '" + path + "'");
}

}

Here are some other people with the same problem, but looks like no solution so far: Drag from SWT to Desktop, ..want destination path as String

Upvotes: 1

Views: 984

Answers (2)

Chris Tarpy
Chris Tarpy

Reputation: 70

You don't get the file location from and write the file yourself. Dragging to the Desktop implies a FileTransfer (you can check what type of transfer is supported in dragSetData).

This means that SWT expecting a String[] of file paths in DragSourceEvent.data. If you set this in the dragSetData method, then SWT copies those files to your drop target - e.g. the Desktop.

        @Override
        public void dragSetData(DragSourceEvent e) {
            System.out.println("--dragSetData--");

            System.out.println("Is supported: "  + FileTransfer.getInstance().isSupportedType(e.dataType));

            FileTransfer f = FileTransfer.getInstance();
            String[] filePaths = {"C:\\CamelOut\\4.xml" }  ;
            e.data = filePaths; 
        }
    };

Upvotes: 1

Eugene
Eugene

Reputation: 9474

The only way to do it is by creating a temporary file and then using the FileTransfer. I suspect that's what you'd have to do in native code anyways. I'll see if I have enough time to sketch the sample...

Upvotes: 1

Related Questions