art with code

2008-12-13

Filezoo day 32: drag and drop handling

Added a handler for dealing with data dropped onto the Filezoo window. It copies or moves the source uri list (Konqueror, Nautilus, Firefox and others pass the DnD'd files as \r\n-separated strings of URIs) over to the drag target directory using Gnome-VFS. So now I can drag an image from Firefox onto a Filezoo directory and it'll be copied there.

The implementation was a wee bit challenging, since there was very little documentation for doing DragDrop event handling and perhaps even less for the Gnome.Vfs namespace. Here's what I used:

Handling data dropped on the widget, this is from the widget constructor:

TargetEntry[] target_table = new TargetEntry [] {
new TargetEntry ("text/uri-list", 0, 0),
new TargetEntry ("text/plain", 0, 1),
new TargetEntry ("STRING", 0, 1)
};

DragDataReceived += delegate (object sender, DragDataReceivedArgs e) {
string type = e.SelectionData.Type.Name;
Console.WriteLine(type);
Gdk.DragAction action = e.Context.SuggestedAction;
if (type == "text/uri-list" || (type == "text/plain" && IsURI(e.SelectionData.Text))) {
string data = new System.Text.ASCIIEncoding().GetString(e.SelectionData.Data);
string[] uris = data.Split(new char[] {'\r','\n','\0'},
StringSplitOptions.RemoveEmptyEntries);
string msg = action.ToString() + " " + String.join(", ", uris);
} else {
Console.WriteLine("Got {0}", e.SelectionData.Text);
}
);

Gtk.Drag.DestSet (this, DestDefaults.All, target_table,
Gdk.DragAction.Move
| Gdk.DragAction.Copy
| Gdk.DragAction.Ask
);

Using Gnome-VFS XferUriList to do a copy or move:

public static void XferURIs
(Gnome.Vfs.Uri[] sources, Gnome.Vfs.Uri[] targets, bool removeSources)
{
XferURIs (sources, targets, removeSources, ConsoleXferProgressCallback);
}

public static void XferURIs
(Gnome.Vfs.Uri[] sources, Gnome.Vfs.Uri[] targets, bool removeSources,
Gnome.Vfs.XferProgressCallback callback)
{
Gnome.Vfs.Vfs.Initialize ();
Gnome.Vfs.XferOptions mode = Gnome.Vfs.XferOptions.Recursive;
if (removeSources) mode = mode | Gnome.Vfs.XferOptions.Removesource;
Gnome.Vfs.Xfer.XferUriList (
sources, targets, mode,
Gnome.Vfs.XferErrorMode.Query,
Gnome.Vfs.XferOverwriteMode.Replace,
callback
);
}

public static int ConsoleXferProgressCallback (Gnome.Vfs.XferProgressInfo info)
{
switch (info.Status) {
case Gnome.Vfs.XferProgressStatus.Vfserror:
Console.WriteLine("{0}: {1} in {2} -> {3}",
info.Status, info.VfsStatus, info.SourceName, info.TargetName);
return (int)Gnome.Vfs.XferErrorAction.Abort;
case Gnome.Vfs.XferProgressStatus.Overwrite:
Console.WriteLine("{0}: {1} in {2} -> {3}",
info.Status, info.VfsStatus, info.SourceName, info.TargetName);
return (int)Gnome.Vfs.XferOverwriteAction.Abort;
default:
Console.WriteLine("{0} / {1} {2} -> {3}",
info.BytesCopied, info.BytesTotal, info.SourceName, info.TargetName);
return 1;
}
}

(Now I need a pimpin' progress indicator... maybe an arc to the dir with "incoming $STUFF -." or something with ambient notifications. Maybe just pop up a plain jane Gtk progress dialog :P)

Next features on this path would be dragging things around, navigating while dragging (think Finder's space-to-descend on steroids), and handling cut-copy-paste.
Post a Comment

Blog Archive

About Me

My Photo

Built art installations, web sites, graphics libraries, web browsers, mobile apps, desktop apps, media player themes, many nutty prototypes, much bad code, much bad art.

Have freelanced for Verizon, Google, Mozilla, Warner Bros, Sony Pictures, Yahoo!, Microsoft, Valve Software, TDK Electronics.

Ex-Chrome Developer Relations.