|
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 Threads | Posted | | 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 |
|