summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/Tk/DragDrop.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Tk/DragDrop.pm')
-rw-r--r--Master/tlpkg/tlperl/lib/Tk/DragDrop.pm332
1 files changed, 332 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/Tk/DragDrop.pm b/Master/tlpkg/tlperl/lib/Tk/DragDrop.pm
new file mode 100644
index 00000000000..46bbacddc26
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Tk/DragDrop.pm
@@ -0,0 +1,332 @@
+package Tk::DragDrop;
+require Tk::DragDrop::Common;
+require Tk::Toplevel;
+require Tk::Label;
+
+use vars qw($VERSION);
+$VERSION = '4.015'; # sprintf '4.%03d', q$Revision: #14 $ =~ /\D(\d+)\s*$/;
+
+use base qw(Tk::DragDrop::Common Tk::Toplevel);
+
+# This is a little tricky, ISA says 'Toplevel' but we
+# define a Tk_cmd to actually build a 'Label', then
+# use wmRelease in Populate to make it a toplevel.
+
+my $useWmRelease = Tk::Wm->can('release'); # ($^O ne 'MSWin32');
+
+sub Tk_cmd { ($useWmRelease) ? \&Tk::label : \&Tk::toplevel }
+
+Construct Tk::Widget 'DragDrop';
+
+use strict;
+use vars qw(%type @types);
+use Carp;
+
+
+# There is a snag with having a token window and moving to
+# exactly where cursor is - the cursor is "inside" the token
+# window - hence it is not "inside" the dropsite window
+# so we offset X,Y by OFFSET pixels.
+sub OFFSET () {3}
+
+sub ClassInit
+{
+ my ($class,$mw) = @_;
+ $mw->bind($class,'<Map>','Mapped');
+ $mw->bind($class,'<Any-KeyPress>','Done');
+ $mw->bind($class,'<Any-ButtonRelease>','Drop');
+ $mw->bind($class,'<Any-Motion>','Drag');
+ return $class;
+}
+
+sub Populate
+{
+ my ($token,$args) = @_;
+ my $parent = $token->parent;
+ if ($useWmRelease)
+ {
+ $token->wmRelease;
+ $token->ConfigSpecs(-text => ['SELF','text','Text',$parent->class]);
+ }
+ else
+ {
+ my $lab = $token->Label->pack(-expand => 1, -fill => 'both');
+ bless $lab,ref($token);
+ $lab->bindtags([ref($token), $lab, $token, 'all']);
+ $token->ConfigSpecs(-text => [$lab,'text','Text',$parent->class],
+ DEFAULT => [$lab]);
+ }
+ $token->withdraw;
+ $token->overrideredirect(1);
+ $token->ConfigSpecs(-sitetypes => ['METHOD','siteTypes','SiteTypes',undef],
+ -startcommand => ['CALLBACK',undef,undef,undef],
+ -endcommand => ['CALLBACK',undef,undef,undef],
+ -predropcommand => ['CALLBACK',undef,undef,undef],
+ -postdropcommand => ['CALLBACK',undef,undef,undef],
+ -delta => ['PASSIVE','delta','Delta',10],
+ -cursor => ['SELF','cursor','Cursor','hand2'],
+ -handlers => ['SETMETHOD','handlers','Handlers',[[[$token,'SendText']]]],
+ -selection => ['SETMETHOD','selection','Selection','XdndSelection'],
+ -event => ['SETMETHOD','event','Event','<B1-Motion>']
+ );
+ $token->{InstallHandlers} = 0;
+ $args->{-borderwidth} = 3;
+ $args->{-relief} = 'flat';
+ $args->{-takefocus} = 1;
+}
+
+sub sitetypes
+{
+ my ($w,$val) = @_;
+ confess "Not a widget $w" unless (ref $w);
+ my $var = \$w->{Configure}{'-sitetypes'};
+ if (@_ > 1)
+ {
+ if (defined $val)
+ {
+ $val = [$val] unless (ref $val);
+ my $type;
+ foreach $type (@$val)
+ {
+ Tk::DragDrop->import($type);
+ }
+ }
+ $$var = $val;
+ }
+ return (defined $$var) ? $$var : \@types;
+}
+
+sub SendText
+{
+ my ($w,$offset,$max) = @_;
+ my $s = substr($w->cget('-text'),$offset);
+ $s = substr($s,0,$max) if (length($s) > $max);
+ return $s;
+}
+
+sub handlers
+{
+ my ($token,$opt,$value) = @_;
+ $token->{InstallHandlers} = (defined($value) && @$value);
+ $token->{'handlers'} = $value;
+}
+
+sub selection
+{
+ my ($token,$opt,$value) = @_;
+ my $handlers = $token->{'handlers'};
+ $token->{InstallHandlers} = (defined($handlers) && @$handlers);
+}
+
+sub event
+{
+ my ($w,$opt,$value) = @_;
+ # delete old bindings
+ $w->parent->Tk::bind($value,[$w,'StartDrag']);
+}
+
+#
+
+sub FindSite
+{
+ my ($token,$X,$Y,$e) = @_;
+ my $site;
+ my $types = $token->sitetypes;
+ if (defined $types && @$types)
+ {
+ foreach my $type (@$types)
+ {
+ my $class = $type{$type};
+ last if (defined($class) && ($site = $class->FindSite($token,$X,$Y)));
+ }
+ }
+ else
+ {
+ warn 'No sitetypes';
+ }
+ my $new = $site || 'undef';
+ my $over = $token->{'Over'};
+ if ($over)
+ {
+ if (!$over->Match($site))
+ {
+ $over->Leave($token,$e);
+ delete $token->{'Over'};
+ }
+ }
+ if ($site)
+ {
+ unless ($token->{'Over'})
+ {
+ $site->Enter($token,$e);
+ $token->{'Over'} = $site;
+ }
+ $site->Motion($token,$e) if (defined $site)
+ }
+ return $site;
+}
+
+sub Mapped
+{
+ my ($token) = @_;
+ my $e = $token->parent->XEvent;
+ $token = $token->toplevel;
+ $token->grabGlobal;
+ $token->focus;
+ if (defined $e)
+ {
+ my $X = $e->X;
+ my $Y = $e->Y;
+ $token->MoveToplevelWindow($X+OFFSET,$Y+OFFSET);
+ $token->NewDrag;
+ $token->FindSite($X,$Y,$e);
+ }
+}
+
+sub NewDrag
+{
+ my ($token) = @_;
+ my $types = $token->sitetypes;
+ if (defined $types && @$types)
+ {
+ my $type;
+ foreach $type (@$types)
+ {
+ my $class = $type{$type};
+ if (defined $class)
+ {
+ $class->NewDrag($token);
+ }
+ }
+ }
+}
+
+sub Drag
+{
+ my $token = shift;
+ my $e = $token->XEvent;
+ my $X = $e->X;
+ my $Y = $e->Y;
+ $token = $token->toplevel;
+ $token->MoveToplevelWindow($X+OFFSET,$Y+OFFSET);
+ $token->FindSite($X,$Y,$e);
+}
+
+sub Done
+{
+ my $token = shift;
+ my $e = $token->XEvent;
+ $token = $token->toplevel;
+ my $over = delete $token->{'Over'};
+ $over->Leave($token,$e) if (defined $over);
+ my $w = $token->parent;
+ eval {local $SIG{__DIE__}; $token->grabRelease };
+ $token->withdraw;
+ delete $w->{'Dragging'};
+ $w->update;
+}
+
+sub AcceptDrop
+{
+ my ($token) = @_;
+ $token->configure(-relief => 'sunken');
+ $token->{'Accepted'} = 1;
+}
+
+sub RejectDrop
+{
+ my ($token) = @_;
+ $token->configure(-relief => 'flat');
+ $token->{'Accepted'} = 0;
+}
+
+sub HandleLoose
+{
+ my ($w,$seln) = @_;
+ return '';
+}
+
+sub InstallHandlers
+{
+ my ($token,$seln) = @_;
+ my $w = $token->parent;
+ $token->configure('-selection' => $seln) if $seln;
+ $seln = $token->cget('-selection');
+ if ($token->{InstallHandlers})
+ {
+ foreach my $h (@{$token->cget('-handlers')})
+ {
+ $w->SelectionHandle('-selection' => $seln,@$h);
+ }
+ $token->{InstallHandlers} = 0;
+ }
+ if (!$w->IS($w->SelectionOwner('-selection'=>$seln)))
+ {
+ $w->SelectionOwn('-selection' => $seln, -command => [\&HandleLoose,$w,$seln]);
+ }
+}
+
+sub Drop
+{
+ my $ewin = shift;
+ my $e = $ewin->XEvent;
+ my $token = $ewin->toplevel;
+ my $site = $token->FindSite($e->X,$e->Y,$e);
+ Tk::catch { $token->grabRelease };
+ if (defined $site)
+ {
+ my $seln = $token->cget('-selection');
+ unless ($token->Callback(-predropcommand => $seln, $site))
+ {
+# XXX This is ugly if the user restarts a drag within the 2000 ms:
+# my $id = $token->after(2000,[$token,'Done']);
+ my $w = $token->parent;
+ $token->InstallHandlers;
+ $site->Drop($token,$seln,$e);
+ $token->Callback(-postdropcommand => $seln);
+ $token->Done;
+ }
+ }
+ else
+ {
+ $token->Done;
+ }
+ $token->Callback('-endcommand');
+}
+
+sub StartDrag
+{
+ my $token = shift;
+ my $w = $token->parent;
+ unless ($w->{'Dragging'})
+ {
+ my $e = $w->XEvent;
+ my $X = $e->X;
+ my $Y = $e->Y;
+ my $was = $token->{'XY'};
+ if ($was)
+ {
+ my $dx = $was->[0] - $X;
+ my $dy = $was->[1] - $Y;
+ if (sqrt($dx*$dx+$dy*$dy) > $token->cget('-delta'))
+ {
+ unless ($token->Callback('-startcommand',$token,$e))
+ {
+ delete $token->{'XY'};
+ $w->{'Dragging'} = $token;
+ $token->MoveToplevelWindow($X+OFFSET,$Y+OFFSET);
+ $token->raise;
+ $token->deiconify;
+ $token->FindSite($X,$Y,$e);
+ }
+ }
+ }
+ else
+ {
+ $token->{'XY'} = [$X,$Y];
+ }
+ }
+}
+
+
+1;