RE: Drag-n-Drop in Perl/Tkx

[email protected] ("Swingle David-QWHM86")
Newsgroups perl.tcltk
Message-ID <[email protected]>
Thanks Vadim,

What you sent still doesn't handle dropping from an external source
(windows explorer).  I added more to the script to try to understand
what it is doing.  Still don't understand all the rules as far as what
gets passed around (the "FOO_BAR" text in your example).  Still can't
get external drops.  I took out the Tkx::package_require('tile'), just
in case it was causing problems.

<code>
use strict;
use warnings;
use Tkx;
use Data::Dumper;

my $text = "Drag to here";

Main(@ARGV);
exit(0);

sub Main
{
    local $Tkx::TRACE = 64;
    Tkx::package_require('BWidget');
    DrawGUI();
    Tkx::MainLoop();
}
 
sub DrawGUI
{
    my $wm = Tkx::widget->new(".");
    $wm->g_wm_title("BWidgets Demo for Drag 'n Drop enabled buttons.");

    foreach (1 .. 4) { CreateButton( $wm, $_ ); }
    CreateEntry( $wm );

    $wm->new_Button(-text => "Exit Demo",
                    -command => [ \&Tkx::destroy, '.'
])->g_pack(qw'-padx 5 -pady 5');
}

sub CreateButton
{
    my ($wm, $i) = @_;

    print "CreateButton: $i\n";
    my $m  = (qw' 0 Drag and Drop Demo ')[$i];
    my $button = $wm->new_Button(-name => ".b$i",    # auto-name is .b
.b2 .b3...
                                 -image => Tkx::Bitmap__get( (qw'0 new
file copy redo ')[$i] ),
                                 -text  => "$i.) $m",
                                 -command => sub { print "$m\n"; });
    $button->g_pack;

    print "enable DND for $button\n";
    my $t1 = "DragSiteIncludeButton" . $button;
    my $t2 = "FOOBAR" . $button;
    my $t3 = "DropRegButton" . $button;
    Tkx::DragSite__include('button', $t1, '<B1-Motion>');
    Tkx::DropSite__register($button, 
                            -dropcmd => \&DropCmdButton,
                            -droptypes => Tkx::list("FOOBAR",
Tkx::list('copy', '', 'move', '', 'link', '')),);
    Tkx::DragSite__register($button,
                            -dragevent => 1,
                            -draginitcmd => \&DragInitCmdButton,
                            -dragendcmd => \&DragEndCmdButton);
}

sub CreateEntry
{
    my ($wm) = @_;

    print "CreateEntry\n";
    my $entry = $wm->new_entry(-name => "$wm.e",
                               -width => 20,
                               -textvariable => \$text);
    $entry->g_pack(qw '-padx 5 -pady 5');

    print "enable DND for $entry\n";
    my $data = "DropRegEntry" . $entry;
    my $t1 = "DragSiteIncludeEntry" . $entry;
    Tkx::DragSite__include('entry', "FOOBAR", '<B1-Motion>');
    Tkx::DropSite__register($entry,
                            -dropcmd => \&DropCmdEntry,
                            -dropovercmd => \&DropOverCmdEntry,
                            -droptypes => Tkx::list("FOOBAR",
Tkx::list('copy', '', 'move', '', 'link', '')),);
}

#
# This command is called when user release the drag icon over a valid
drop target widget.
#
sub DropCmdButton
{
    my @args = (@_);
 
    print "\tDropCmdButton:\n";
    print "args[0]:        " . Dumper($args[0]);
    print "args[1]:        " . Dumper($args[1]);
    print "args[2]:        " . Dumper($args[2]);
    print "Drop Target:    $args[3]\n";
    print "Drag Source:    $args[4]\n";
    print "X-Coordinate:   $args[5]\n";
    print "Y-Coordinate:   $args[6]\n";
    print "Operation:      $args[7]\n";
    print "Type of Data:   $args[8]\n";
    print "Dragged Data:   $args[9]\n";

    my $data = "DropCmdButton" . $args[3];

    return Tkx::list("DropCmdButton", "copy", $data);   # passed to
-dragendcmd
}

#
# Command called when drag initiates. When the event of option dragevent
occurs on path.
#
# If the command returns an empty string, then the drag will be
suppressed.
# Otherwise the command must return a list containing three elements:
#   the type of the data
#   the list of acceptable basic operations (copy, move and link)
#   the data
#
# Note that even if copy does not appear in the list of basic operation,
it is considered
# as an acceptable operation, since copy semantic does not modify the
drag source.
#
sub DragInitCmdButton
{
    my @args = (@_);
 
    print "\tDragInitCmdButton:\n";
    print "args[0]:        " . Dumper($args[0]);
    print "args[1]:        " . Dumper($args[1]);
    print "args[2]:        " . Dumper($args[2]);
    print "Drag Source:    $args[3]\n";
    print "X-Coordinate:   $args[4]\n";
    print "Y-Coordinate:   $args[5]\n";
    print "Top Level:      $args[6]\n";

    my $t1 = "FOOBAR" . $args[3];
    my $t2 = "DragInitButton" . $args[3];

    return Tkx::list("FOOBAR", "copy", $t2);        # need FOOBAR - to
match register?
}

#
# Command called when drag terminates (ie when user release drag icon).
#
# If the drop does not occurs, the target and the operation are empty
string and the result is 0.
#
sub DragEndCmdButton
{
    my @args = (@_);
 
    print "\tDragEndCmdButton:\n";
    print "args[0]:        " . Dumper($args[0]);
    print "args[1]:        " . Dumper($args[1]);
    print "args[2]:        " . Dumper($args[2]);
    print "Drag Source:    $args[3]\n";
    print "Drop Target:    $args[4]\n";
    print "Operation:      $args[5]\n";
    print "Type of Data:   $args[6]\n";
    print "Dragged Data:   $args[7]\n";
    print "Result of Drop: $args[8]\n";
}

#
# This command is called when user release the drag icon over a valid
drop target widget.
#
sub DropCmdEntry
{
    my @args = (@_);
 
    print "\tDropCmdEntry:\n";
    print "args[0]:        " . Dumper($args[0]);
    print "args[1]:        " . Dumper($args[1]);
    print "args[2]:        " . Dumper($args[2]);
    print "Drop Target:    $args[3]\n";
    print "Drag Source:    $args[4]\n";
    print "X-Coordinate:   $args[5]\n";
    print "Y-Coordinate:   $args[6]\n";
    print "Operation:      $args[7]\n";
    print "Type of Data:   $args[8]\n";
    print "Dragged Data:   $args[9]\n";

    return Tkx::list("FOOBAR", "copy", "entry");    # passed to
-dragendcmd
}

#
# This command can be used to provide a dynamic drag while drag-over
events.
# While a drag occurs, events <Enter>, <Motion> and <Leave> are caught.
#
# Here is a list of events and associated actions on a DropSite widget.
# This example assumes that dragged data type is valid for the drop
target.
# status is the status of the drag on a DropSite. Its value is:
#
# Event     Old status  Action
New status
#
------------------------------------------------------------------------
------------
# <Enter>   -           if DropSite has dropovercmd, call it with enter
result of dropovercmd
#                       else
1
# <Motion>  0 or 1
unchanged
#           2 or 3      call dropovercmd with motion
result of dropovercmd
# <Leave>   0 or 1
-
#           2 or 3      call dropovercmd with leave
-
# <Drop>    0           call dragendcmd of drag source
-
#           1           call dropcmd and call dragendcmd of drag source
#           2           call dropovercmd with leave and call dragendcmd
of drag source
#           3           call dropcmd and call dragendcmd of drag source
#
sub DropOverCmdEntry
{
    my @args = (@_);
 
    print "\tDropOverCmdEntry:\n";
    print "args[0]:        " . Dumper($args[0]);
    print "args[1]:        " . Dumper($args[1]);
    print "args[2]:        " . Dumper($args[2]);
    print "Drop Target:    $args[3]\n";
    print "Drag Source:    $args[4]\n";
    print "Event:          $args[5]\n";
    print "X-Coordinate:   $args[6]\n";
    print "Y-Coordinate:   $args[7]\n";
    print "Operation:      $args[8]\n";
    print "Type of Data:   $args[9]\n";
    print "Dragged Data:   $args[10]\n";

    # Return values:
    # 0 if widget refuse this drag. Command will not be recalled on
motion/leave event.
    # 1 if widget accept this drag. Command will not be recalled on
motion/leave event.
    # 2 if widget refuse this drag. Command will be recalled on each
motion event to reevaluate.
    # 3 if widget accept this drag. Command will be recalled on each
motion event to reevaluate.
    return 1;
}
</code>

When I run the script and drag the 1st button and drop on the 2nd
button, and then drag the 3rd button and drop on the entry widget, I get
the following:

<code>
Tkx-1-0.0s-dnd6.pl-14: package require BWidget
Tkx-2-0.0s-dnd6.pl-22: wm title . {BWidgets Demo for Drag 'n Drop
enabled buttons.}
CreateButton: 1
Tkx-3-0.0s-dnd6.pl-40: Bitmap::get new
Tkx-4-0.0s-dnd6.pl-40: Button .b1 -image image1 -text {1.) Drag}
-command perl::callback
Tkx-5-0.0s-dnd6.pl-41: pack .b1
enable DND for .b1
Tkx-6-0.0s-dnd6.pl-48: DragSite::include button DragSiteIncludeButton.b1
<B1-Motion>
Tkx-7-0.0s-dnd6.pl-49: list copy  move  link
Tkx-8-0.0s-dnd6.pl-49: list FOOBAR [list copy {} move {} link {}]
Tkx-9-0.0s-dnd6.pl-49: DropSite::register .b1 -dropcmd perl::callback
-droptypes [list FOOBAR {copy {} move {} link {}}]
Tkx-10-0.0s-dnd6.pl-52: DragSite::register .b1 -dragevent 1 -draginitcmd
perl::callback -dragendcmd perl::callback
CreateButton: 2
Tkx-11-0.0s-dnd6.pl-40: Bitmap::get file
Tkx-12-0.1s-dnd6.pl-40: Button .b2 -image image2 -text {2.) and}
-command perl::callback
Tkx-13-0.1s-dnd6.pl-41: pack .b2
enable DND for .b2
Tkx-14-0.1s-dnd6.pl-48: DragSite::include button
DragSiteIncludeButton.b2 <B1-Motion>
Tkx-15-0.1s-dnd6.pl-49: list copy  move  link
Tkx-16-0.1s-dnd6.pl-49: list FOOBAR [list copy {} move {} link {}]
Tkx-17-0.1s-dnd6.pl-49: DropSite::register .b2 -dropcmd perl::callback
-droptypes [list FOOBAR {copy {} move {} link {}}]
Tkx-18-0.1s-dnd6.pl-52: DragSite::register .b2 -dragevent 1 -draginitcmd
perl::callback -dragendcmd perl::callback
CreateButton: 3
Tkx-19-0.1s-dnd6.pl-40: Bitmap::get copy
Tkx-20-0.1s-dnd6.pl-40: Button .b3 -image image3 -text {3.) Drop}
-command perl::callback
Tkx-21-0.1s-dnd6.pl-41: pack .b3
enable DND for .b3
Tkx-22-0.1s-dnd6.pl-48: DragSite::include button
DragSiteIncludeButton.b3 <B1-Motion>
Tkx-23-0.1s-dnd6.pl-49: list copy  move  link
Tkx-24-0.1s-dnd6.pl-49: list FOOBAR [list copy {} move {} link {}]
Tkx-25-0.1s-dnd6.pl-49: DropSite::register .b3 -dropcmd perl::callback
-droptypes [list FOOBAR {copy {} move {} link {}}]
Tkx-26-0.1s-dnd6.pl-52: DragSite::register .b3 -dragevent 1 -draginitcmd
perl::callback -dragendcmd perl::callback
CreateButton: 4
Tkx-27-0.1s-dnd6.pl-40: Bitmap::get redo
Tkx-28-0.1s-dnd6.pl-40: Button .b4 -image image4 -text {4.) Demo}
-command perl::callback
Tkx-29-0.1s-dnd6.pl-41: pack .b4
enable DND for .b4
Tkx-30-0.1s-dnd6.pl-48: DragSite::include button
DragSiteIncludeButton.b4 <B1-Motion>
Tkx-31-0.1s-dnd6.pl-49: list copy  move  link
Tkx-32-0.1s-dnd6.pl-49: list FOOBAR [list copy {} move {} link {}]
Tkx-33-0.1s-dnd6.pl-49: DropSite::register .b4 -dropcmd perl::callback
-droptypes [list FOOBAR {copy {} move {} link {}}]
Tkx-34-0.1s-dnd6.pl-52: DragSite::register .b4 -dragevent 1 -draginitcmd
perl::callback -dragendcmd perl::callback
CreateEntry
Tkx-35-0.1s-dnd6.pl-63: entry ..e -width 20 -textvariable
SCALAR(0x18301a0)
Tkx-36-0.1s-dnd6.pl-66: pack .e -padx 5 -pady 5
enable DND for .e
Tkx-37-0.1s-dnd6.pl-71: DragSite::include entry FOOBAR <B1-Motion>
Tkx-38-0.1s-dnd6.pl-72: list copy  move  link
Tkx-39-0.1s-dnd6.pl-72: list FOOBAR [list copy {} move {} link {}]
Tkx-40-0.1s-dnd6.pl-72: DropSite::register .e -dropcmd perl::callback
-dropovercmd perl::callback -droptypes [list FOOBAR {copy {} m
ove {} link {}}]
Tkx-41-0.1s-dnd6.pl-27: winfo children .
Tkx-42-0.1s-dnd6.pl-27: Button .b -text {Exit Demo} -command
perl::callback
Tkx-43-0.1s-dnd6.pl-27: pack .b -padx 5 -pady 5
        DragInitCmdButton:
args[0]:        $VAR1 = undef;
args[1]:        $VAR1 = bless( do{\(my $o = 26882256)}, 'Tcl' );
args[2]:        $VAR1 = '::perl::CODE(0x1aee6ec)';
Drag Source:    .b1
X-Coordinate:   122
Y-Coordinate:   74
Top Level:      .drag
Tkx-44-3.4s-dnd6.pl-130: list FOOBAR copy DragInitButton.b1
        DropCmdButton:
args[0]:        $VAR1 = undef;
args[1]:        $VAR1 = bless( do{\(my $o = 26882256)}, 'Tcl' );
args[2]:        $VAR1 = '::perl::CODE(0x1aee194)';
Drop Target:    .b2
Drag Source:    .b1
X-Coordinate:   112
Y-Coordinate:   97
Operation:      default
Type of Data:   FOOBAR
Dragged Data:   DragInitButton.b1
Tkx-45-5.3s-dnd6.pl-99: list DropCmdButton copy DropCmdButton.b2
        DragEndCmdButton:
args[0]:        $VAR1 = undef;
args[1]:        $VAR1 = bless( do{\(my $o = 26882256)}, 'Tcl' );
args[2]:        $VAR1 = '::perl::CODE(0x1aee8e4)';
Drag Source:    .b1
Drop Target:    .b2
Operation:      copy
Type of Data:   FOOBAR
Dragged Data:   DragInitButton.b1
Result of Drop: DropCmdButton copy DropCmdButton.b2
        DragInitCmdButton:
args[0]:        $VAR1 = undef;
args[1]:        $VAR1 = bless( do{\(my $o = 26882256)}, 'Tcl' );
args[2]:        $VAR1 = '::perl::CODE(0x1aee6ec)';
Drag Source:    .b3
X-Coordinate:   123
Y-Coordinate:   115
Top Level:      .drag
Tkx-46-13.0s-dnd6.pl-130: list FOOBAR copy DragInitButton.b3
        DropOverCmdEntry:
args[0]:        $VAR1 = undef;
args[1]:        $VAR1 = bless( do{\(my $o = 26882256)}, 'Tcl' );
args[2]:        $VAR1 = '::perl::CODE(0x1aeedf4)';
Drop Target:    .e
Drag Source:    .b3
Event:          enter
X-Coordinate:   157
Y-Coordinate:   159
Operation:      default
Type of Data:   FOOBAR
Dragged Data:   DragInitButton.b3
        DropCmdEntry:
args[0]:        $VAR1 = undef;
args[1]:        $VAR1 = bless( do{\(my $o = 26882256)}, 'Tcl' );
args[2]:        $VAR1 = '::perl::CODE(0x1aeeb54)';
Drop Target:    .e
Drag Source:    .b3
X-Coordinate:   148
Y-Coordinate:   164
Operation:      default
Type of Data:   FOOBAR
Dragged Data:   DragInitButton.b3
Tkx-47-14.8s-dnd6.pl-173: list FOOBAR copy entry
        DragEndCmdButton:
args[0]:        $VAR1 = undef;
args[1]:        $VAR1 = bless( do{\(my $o = 26882256)}, 'Tcl' );
args[2]:        $VAR1 = '::perl::CODE(0x1aee8e4)';
Drag Source:    .b3
Drop Target:    .e
Operation:      copy
Type of Data:   FOOBAR
Dragged Data:   DragInitButton.b3
Result of Drop: FOOBAR copy entry
Tkx-48-18.6s-Tcl.pm-512: destroy .
</code>

Dave
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.