Click here to get back home

Tk::DropSite question

 HomeNewsGroups | Search | About
 comp.lang.perl.modules    Post an article   get this group's latest topics as an RSS feed add this group's latest topics to your My MSN content add this group's latest topics to your My Yahoo content
Subject Author Date
Tk::DropSite question ~greg 03-04-2007
Posted by ~greg on March 4, 2007, 4:10 pm
Please log in for more thread options


I have reduced the following script,
but it's runnable. It's a way
to make a Tk listbox that accepts
a selection of files or folders
from Windows Explorer.

The drop handler (my "OnSourceDrop")
is apparently called individually
on each file or folder in a multiple selection.

And my question is,

is there any way to know when to call
a group-drop-handler,
to be called after all the individual
calls to OnSourceDrop() are finished
after a group drop?

thank you,

~greg

~~~~~~~~~~~~~~~~~~~~~~


use strict;
use warnings;
$|=1;

use Tk;
use Tk::DropSite qw(Win32);

my $Main = MainWindow->new
(
-title=>'DND'
);

my %SourceList;

my $SourceListBox = $Main->Scrolled
(
"Listbox",
-scrollbars => "osoe",
)->pack
(
-fill => 'x',
);

$SourceListBox->DropSite
(
-dropcommand => [\&OnSourceDrop,$SourceListBox],
-droptypes => 'Win32',
);

sub SourceAdd
{
my $f = shift; # file or folder
return if exists $SourceList;
return if ! -e $f;
$SourceList = 1;
my $slash = -d $f ? '\' : '';
$SourceListBox->insert('end', "$f$slash" );
$SourceListBox->yviewMoveto(1);
}

sub OnSourceDrop
{
my($widget, $selection) = @_;
my $f = $widget->SelectionGet('-selection'=>$selection,'STRING');
return if ! defined $f; # is this really necessary?
SourceAdd($f);
}

MainLoop;



Posted by Ch Lamprecht on March 4, 2007, 6:04 pm
Please log in for more thread options


~greg wrote:
> I have reduced the following script,
> but it's runnable. It's a way
> to make a Tk listbox that accepts
> a selection of files or folders
> from Windows Explorer.
>
> The drop handler (my "OnSourceDrop")
> is apparently called individually
> on each file or folder in a multiple selection.
>
> And my question is,
>
> is there any way to know when to call
> a group-drop-handler,
> to be called after all the individual
> calls to OnSourceDrop() are finished
> after a group drop?


One way is setting up a timer:
This one will trigger group_drop_handler 50ms after the last call to
OnSourceDrop. Are groups with one element considered being groups in your case?
Otherwise you would have to add a counter...



>
>
> use strict;
> use warnings;
> $|=1;
>
> use Tk;
> use Tk::DropSite qw(Win32);
>
> my $Main = MainWindow->new
> (
> -title=>'DND'
> );
>
> my %SourceList;
>
> my $SourceListBox = $Main->Scrolled
> (
> "Listbox",
> -scrollbars => "osoe",
> )->pack
> (
> -fill => 'x',
> );
>
> $SourceListBox->DropSite
> (
> -dropcommand => [\&OnSourceDrop,$SourceListBox],
> -droptypes => 'Win32',
> );
>
> sub SourceAdd
> {
> my $f = shift; # file or folder
> return if exists $SourceList;
> return if ! -e $f;
> $SourceList = 1;
> my $slash = -d $f ? '\' : '';
> $SourceListBox->insert('end', "$f$slash" );
> $SourceListBox->yviewMoveto(1);
> }
>
{
my $after_cb;

> sub OnSourceDrop
> {
> my($widget, $selection) = @_;
$widget->afterCancel($after_cb);
$after_cb = $widget->after(50,\&group_drop_handler);

> my $f = $widget->SelectionGet('-selection'=>$selection,'STRING');
> return if ! defined $f; # is this really necessary?
> SourceAdd($f);
> }
}
>
> MainLoop;

sub group_drop_handler{
print "group drop finished\n";
}

Christoph



--
use Tk;use Tk::GraphItems;$c=tkinit->Canvas->pack;push@i,Tk::GraphItems->
TextBox(text=>$_,canvas=>$c,x=>$x+=70,y=>100)for(Just=>another=>Perl=>Hacker);
Tk::GraphItems->Connector(source=>$i[$_],target=>$i[$_+1])for(0..2);
$c->repeat(30,sub);MainLoop

Posted by ~greg on March 4, 2007, 8:25 pm
Please log in for more thread options



"Ch Lamprecht" > wrote ...
> One way is setting up a timer:
> This one will trigger group_drop_handler 50ms after the last call to
OnSourceDrop. Are groups with one element considered being
> groups in your case?
> Otherwise you would have to add a counter...

- nah, singletons aren't special in this.

(- one thing that might come up later though
is how to block drops while the last drop
is still being processed - because the processing
could take a lot of time.
But I think I'm already thinking of a way to do this ....)

~

Thank you!

I understand it.
As long as the calls to OnSourceDrop
come within 50 milliseconds of each other,
then the delayed call to the group_drop_handler()
is continuously canceled.

But as soon as OnSourceDrop has not been
called within 50 milliseconds of the last time
it was called, then the call to the
group_drop_hander goes through.

It works!
And I'm sure it's robust enough.

But I was kinda hoping for something
that didn't depend on timing. :)

Following up on your suggestion,
I found, and then substituted, ->afterIdle()
for ->after().

And this works too.

And I also added a print in OnSourceDrop,
and (together with $|=1) this seems to show me
that it's all working in proper order.

I'm guessing that group-dropped items are all
put into the event queue at the same time,
and that that's why ->afterIdle() works,

and that it is ok if some other random event happens
to fall into the event queue before the ->afterIdle fires,
because that would simply delay the group_drop_handler
a bit longer, -- which is what your ->after(50,...) does too ...

So, would you agree that ->afterIdle() is better?
Or could there be some problem with it?


Thank you!

~greg


~~~~~~~
# changed to using ->afterIdle() instead of ->after()
# and in putting a print in OnSourceDrop()
# ...

use strict;
use warnings;
$|=1;

use Tk;
use Tk::DropSite qw(Win32);

my $Main = MainWindow->new
(
-title=>'DND'
);

my %SourceList;

my $SourceListBox = $Main->Scrolled
(
"Listbox",
-scrollbars => "osoe",
)->pack
(
-fill => 'x',
);

$SourceListBox->DropSite
(
-dropcommand => [\&OnSourceDrop,$SourceListBox],
-droptypes => 'Win32',
);

sub SourceAdd
{
my $f = shift; # file or folder
return if exists $SourceList;
return if ! -e $f;
$SourceList = 1;
my $slash = -d $f ? '\' : '';
$SourceListBox->insert('end', "$f$slash" );
$SourceListBox->yviewMoveto(1);
}

my $after_cb;

sub OnSourceDrop
{
print "OnSourceDrop\n";

my($widget, $selection) = @_;
$widget->afterCancel($after_cb);

#$after_cb = $widget->after(50,\&group_drop_handler);
$after_cb = $widget->afterIdle(\&group_drop_handler);

my $f = $widget->SelectionGet('-selection'=>$selection,'STRING');
return if ! defined $f; # is this really necessary?
SourceAdd($f);

}

MainLoop;

sub group_drop_handler
{
print "group drop finished\n";
}














Posted by Ch Lamprecht on March 5, 2007, 5:44 pm
Please log in for more thread options


~greg wrote:
> "Ch Lamprecht" > wrote ...
>
>>One way is setting up a timer:

>
> But I was kinda hoping for something
> that didn't depend on timing. :)
>
> Following up on your suggestion,
> I found, and then substituted, ->afterIdle()
> for ->after().
>
> And this works too.

> So, would you agree that ->afterIdle() is better?
> Or could there be some problem with it?

afterIdle will work as long as no update- method is called by any of the
involved subs.
However, as I read the source of the module I found, that it provides a
mechanism, to do what you need: You can pass a Callback to the -entercommand
option. That will be called with either 0 or 1 as first arg to indicate the
beginning/end of a group_drop. See example below.
(And see another post for a second solution)



use strict;
use warnings;
use Data::Dumper;
use Tk;
use Tk::DropSite qw(Win32);

my $Main = MainWindow->new;
my %SourceList;
my $SourceListBox = $Main->Scrolled("Listbox",
-scrollbars => "osoe",
)->pack(-fill => 'both',
);

$SourceListBox->DropSite( -entercommand => \&drop_state,
-dropcommand => [\&OnSourceDrop,
$SourceListBox],
-droptypes => 'Win32',
);

sub SourceAdd{
my $f = shift; # file or folder
return if exists $SourceList;
return if ! -e $f;
$SourceList = 1;
my $slash = -d $f ? '\' : '';
$SourceListBox->insert('end', "$f$slash" );
$SourceListBox->yviewMoveto(1);
}


sub OnSourceDrop{
print "OnSourceDrop\n";

my($widget, $selection) = @_;
my $f = $widget->SelectionGet('-selection'=>$selection,'STRING');
return if ! defined $f; # is this really necessary?
SourceAdd($f);
}

MainLoop;

sub drop_state{
print 'group drop state: ',$_[0] ? 'started':'finished' , "\n";
}








--
use Tk;use Tk::GraphItems;$c=tkinit->Canvas->pack;push@i,Tk::GraphItems->
TextBox(text=>$_,canvas=>$c,x=>$x+=70,y=>100)for(Just=>another=>Perl=>Hacker);
Tk::GraphItems->Connector(source=>$i[$_],target=>$i[$_+1])for(0..2);
$c->repeat(30,sub);MainLoop

Posted by ~greg on March 5, 2007, 7:04 pm
Please log in for more thread options



Ch Lamprecht , ...



I like this first way best. :)
Beautiful,



Thank you!

~greg






Similar ThreadsPosted
DBI question November 5, 2004, 4:28 pm
Newbie Question January 3, 2005, 4:11 pm
LWP question on windows98 October 7, 2004, 8:19 pm
Question to WIN32::OLE October 14, 2004, 11:34 am
Simple question September 15, 2005, 4:17 am
Getopt::Std question September 7, 2005, 9:42 am
Question regarding databases.. November 18, 2005, 9:41 am
Module Question October 25, 2004, 11:42 am
A question of name space October 31, 2004, 2:55 pm
Mechanize question November 8, 2004, 10:57 pm

Our other projects:

Art Dolls, Fairies and Mermaids - Sunnyfaces.net

Roy's Linux, Programming and Search Engines messages

1-Script XML SitemapXML Sitemap