I'm looking for information on how to do the following in Tcl/Tk:
- A "desktop window" (like the Java JDesktopPane) which contains the
other windows for an application;
- The ability to drag and drop icons between these windows -
specifically dropping items from an icon list into "slots" on other
windows.
Most DnD libraries I see seem to concern themselves with inter-app
DnD, which I do not require. I initially thought that the desktop
window could be a canvas, and on initiating a drag action in a window,
the canvas could grab the mouse, animate the moving icon under the
mouse, then see what part of the window was active when the mouse was
released and send an appropriate message to that part of the app.
Unfortunately, I found this will not work because a) the canvas can't
grab events from its own children (or could it just halt the
inheritance tree?), b) the canvas can't draw the animating icon
because you can't overlap a window with a canvas image (but could it
put the image into the pointer?), and c) the canvas can only tell that
the icon is over the window when it is dropped, not what part of the
window it's over (but can the window find out from a window-local
coordinate?).
Does anyone have any suggestions as to how I could implement this? I
need the program to work on Windows in particular, but it would be
nice if it could be platform independant.
It is quite simple to do intra-app dnd in Tk, and there are
several examples around (IIRC Donal Fellows had a good one,
and I might have written an example or two before). For more
elaborate intra-app dnd, there is the BLT extension, and for
cross-platform (Unix and Windows) dnd (uses Xdnd and OLE dnd)
you can get the tkdnd extension (project at SourceForge). It
works with 8.3.3+.
--
Jeff Hobbs The Tcl Guy
Senior Developer http://www.ActiveState.com/
Tcl Support and Productivity Solutions
It's real easy to do DnD between Tk widgets. Integrating with the desktop
DnD is much more difficult. There's one (or more?) tk DnD demos on the wiki.
Try here for starters:
http://mini.net/cgi-bin/wikit/416.html
more wiki-based DnD info is here, including info on platform-specific DnD:
http://mini.net/cgi-bin/wikit/571.html
For a nice JDesktopPane-type widget, check out mkWidgets at the following:
http://ourworld.compuserve.com/homepages/mmg_kraus/TclCornr.htm
Thank you very much for your help. The mkWidgets looks excellent and the
drag and drop is useful but doesn't have the one thing that I'd really
like: the ability to have the icon being dragged (it's specifically an
icon, probably one out of an mkWidgets iconbox by the look of it :) ) follow
the mouse pointer during the dragging. Is there any way this can be done?
If you want drag and drop between tk and non-tk apps or desktops you have to
use tkdnd. It's the only extension that can handle such interaction.
It also offers the ability to also specify a tk window as an icon,
and the extension will move it around following the cursor.
Under windows though, there is a small problem with the dnd protocol:
when the mouse enters a window that is not a drop target, this icon no more
moves, since windows do not report motion events. A small modification is
needed there so as tkdnd to withdraw this window when the mouse entered
such a window, leaving only the default "no drop" cursor. And for
consistency,
is better to do so under all platforms...
George
Thanks again for your reply. I want the icon-moving thing but I do
*not* need dnd between tk and non-tk apps. The dnd will be between
multiple frames in the same tk app - probably both frames in the
desktoppane metawidget from kwWidgets.
Sure, but I'll leave it as an exercise to the user.
The basic idea is this: create a toplevel window, set the overrideredirect
bit (so you don't see any borders), put whatever stuff you want in it (e.g.
a label with an image), and in the binding script for mouse movement move
the coordinates of the window as the mouse moves. When they release the
mouse button, destroy the image.
You can get real fancy if you want, and peek at the object under the mouse
(the thing you want to drop on top of), and change the image being dragged
dynamically to show whether it is presently droppable or not.
If you are truly stuck making this work, I'll cobble up an example.
Another possibility that occurs to me is to use a Toplevel window as your
DnD icon. You can set its overrideredirect attribute so that the window
manager doesn't add a border or other decorations, and then create bindings
on your main "desktop" window to manage displaying and dragging it around.
Here's a quick skeleton of what I had in mind:
#############################################
# Create a toplevel window as our DnD icon window
toplevel .dnd
# Add a decorative frame
frame .dnd.icon -bd 2 -relief groove
pack .dnd.icon
# Put anything you like inside
label .dnd.icon.img -bitmap info
label .dnd.icon.text -text "I'm a draggin'!"
pack .dnd.icon.img .dnd.icon.text -side left -padx 2 -pady 2
# Tell the window manager not to add borders or
# other decorations. Hide the DnD window.
wm overrideredirect .dnd 1
wm withdraw .dnd
# Create your main window interface
canvas .desktop
pack .desktop -expand yes -fill both
# Create click, drag, and release bindings on our
# main window to manage our DnD window.
bind . <ButtonPress-1> {DragStart %X %Y}
bind . <B1-Motion> {DragMove %X %Y}
bind . <ButtonRelease-1> {DragEnd %X %Y}
proc DragStart {x y} {
# You can fiddle with the coordinates as you like
# to place the window relative to the current
# mouse position
set x [expr {$x - ([winfo reqwidth .dnd] / 2)}]
set y [expr {$y - [winfo reqheight .dnd] + 4}]
# Place the DnD window at the given coordinates
# and display the window
wm geometry .dnd +$x+$y
wm deiconify .dnd
}
proc DragMove {x y} {
# Update the position of the DnD window to reflect
# the latest mouse position
set x [expr {$x - ([winfo reqwidth .dnd] / 2)}]
set y [expr {$y - [winfo reqheight .dnd] + 4}]
wm geometry .dnd +$x+$y
}
proc DragEnd {x y} {
# Hide the DnD window
wm withdraw .dnd
# Do whatever sanity checking you need to do to
# make sure we've dropped on a legal target.
}
#################################
- Ken Jones, President
Avia Training and Consulting
www.avia-training.com
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax