home *** CD-ROM | disk | FTP | other *** search
/ Netrunner 2004 October / NETRUNNER0410.ISO / regular / ActivePerl-5.8.4.810-MSWin32-x86.msi / _840abff889333df67cf55526242b2310 < prev    next >
Encoding:
Text File  |  2004-06-01  |  5.2 KB  |  258 lines

  1. package Tk::DropSite;
  2. require Tk::DragDrop::Common;
  3. require Tk::DragDrop::Rect;
  4.  
  5. use vars qw($VERSION);
  6. $VERSION = sprintf '4.%03d', q$Revision: #7 $ =~ /\D(\d+)\s*$/;
  7.  
  8. use base  qw(Tk::DragDrop::Common Tk::DragDrop::Rect);
  9.  
  10. Construct Tk::Widget 'DropSite';
  11.  
  12. use strict;
  13. use vars qw(%type @types);
  14.  
  15. Tk::DragDrop->Tk::DragDrop::Common::Type('Local');
  16.  
  17. my @toplevels;
  18.  
  19. BEGIN
  20. {
  21.  # Are these really methods of Tk::DragDrop::Rect ?
  22.  no strict 'refs';
  23.  foreach my $name (qw(x y X Y width height widget))
  24.   {
  25.    my $key = $name;
  26.    *{"$key"} = sub { shift->{$key} };
  27.   }
  28. }
  29.  
  30. # Dropping side API - really only here for Local drops
  31. # inheritance is a mess right now.
  32.  
  33. sub NewDrag
  34. {
  35.  my ($class,$token) = @_;
  36.  # No need to clear cached sites we see live data
  37. }
  38.  
  39. sub SiteList
  40. {
  41.  # this should be inheritable - so that receive side of XDND can re-use it.
  42.  my ($class,$widget) = @_;
  43.  my $t;
  44.  my @list;
  45.  foreach $t (@toplevels)
  46.   {
  47.    my $sites = $t->{'DropSites'};
  48.    if ($sites)
  49.     {
  50.      $sites = $sites->{'Local'};
  51.      push(@list,@{$sites}) if ($sites);
  52.     }
  53.   }
  54.  return @list;
  55. }
  56.  
  57. sub Apply
  58. {
  59.  my $site = shift;
  60.  my $name = shift;
  61.  my $cb   = $site->{$name};
  62.  if ($cb)
  63.   {
  64.    my $X = shift;
  65.    my $Y = shift;
  66.    $cb->Call(@_,$X - $site->X, $Y - $site->Y);
  67.   }
  68. }
  69.  
  70. sub Drop
  71. {
  72.  my ($site,$token,$seln,$event) = @_;
  73.  my $X = $event->X;
  74.  my $Y = $event->Y;
  75.  my @targ = $token->SelectionGet(-selection => $seln,'TARGETS');
  76.  $site->Apply(-dropcommand => $X, $Y, $seln,'LocalDrop',\@targ);
  77.  $site->Apply(-entercommand => $X, $Y, 0);
  78.  $token->Done;
  79. }
  80.  
  81. sub Enter
  82. {
  83.  my ($site,$token,$event) = @_;
  84.  $token->AcceptDrop;
  85.  $site->Apply(-entercommand => $event->X, $event->Y, 1);
  86. }
  87.  
  88. sub Leave
  89. {
  90.  my ($site,$token,$event) = @_;
  91.  $token->RejectDrop;
  92.  $site->Apply(-entercommand => $event->X, $event->Y, 0);
  93. }
  94.  
  95. sub Motion
  96. {
  97.  my ($site,$token,$event) = @_;
  98.  $site->Apply(-motioncommand => $event->X, $event->Y);
  99. }
  100.  
  101. # This is receive side API.
  102.  
  103. sub NoteSites
  104. {
  105.  my ($class,$t,$sites) = @_;
  106.  unless (grep($_ == $t,@toplevels))
  107.   {
  108.    $Tk::DragDrop::types{'Local'} = $class if (@$sites);
  109.    push(@toplevels,$t);
  110.    $t->OnDestroy(sub { @toplevels = grep($_ != $t,@toplevels) });
  111.   }
  112. }
  113.  
  114. sub UpdateDropSites
  115. {
  116.  my ($t) = @_;
  117.  $t->{'DropUpdate'} = 0;
  118.  foreach my $type (@types)
  119.   {
  120.    my $sites = $t->{'DropSites'}->{$type};
  121.    if ($sites && @$sites)
  122.     {
  123.      my $class = $type{$type};
  124.      $class->NoteSites($t,$sites);
  125.     }
  126.   }
  127. }
  128.  
  129. sub QueueDropSiteUpdate
  130. {
  131.  my $obj = shift;
  132.  my $class = ref($obj);
  133.  my $t   = $obj->widget->toplevel;
  134.  unless ($t->{'DropUpdate'})
  135.   {
  136.    $t->{'DropUpdate'} = 1;
  137.    $t->afterIdle(sub { UpdateDropSites($t) });
  138.   }
  139. }
  140.  
  141. sub delete
  142. {
  143.  my ($obj) = @_;
  144.  my $w = $obj->widget;
  145.  $w->bindtags([grep($_ ne $obj,$w->bindtags)]);
  146.  my $t = $w->toplevel;
  147.  foreach my $type (@{$obj->{'-droptypes'}})
  148.   {
  149.    my $a = $t->{'DropSites'}->{$type};
  150.    @$a   = grep($_ ne $obj,@$a);
  151.   }
  152.  $obj->QueueDropSiteUpdate;
  153. }
  154.  
  155. sub DropSiteUpdate
  156. {
  157.  # Note size of widget and arrange to update properties etc.
  158.  my $obj = shift;
  159.  my $w   = $obj->widget;
  160.  $obj->{'x'}      = $w->X;
  161.  $obj->{'y'}      = $w->Y;
  162.  $obj->{'X'}      = $w->rootx;
  163.  $obj->{'Y'}      = $w->rooty;
  164.  $obj->{'width'}  = $w->Width;
  165.  $obj->{'height'} = $w->Height;
  166.  $obj->QueueDropSiteUpdate;
  167. }
  168.  
  169. sub TopSiteUpdate
  170. {
  171.  my ($t) = @_;
  172.  foreach my $type (@types)
  173.   {
  174.    my $sites = $t->{'DropSites'}->{$type};
  175.    if ($sites && @$sites)
  176.     {
  177.      my $site;
  178.      foreach $site (@$sites)
  179.       {
  180.        $site->DropSiteUpdate;
  181.       }
  182.     }
  183.   }
  184. }
  185.  
  186. sub Callback
  187. {
  188.  my $obj = shift;
  189.  my $key = shift;
  190.  my $cb  = $obj->{$key};
  191.  $cb->Call(@_) if (defined $cb);
  192. }
  193.  
  194. sub InitSite
  195. {
  196.  my ($class,$site) = @_;
  197.  # Tk::DragDrop->Type('Local');
  198. }
  199.  
  200. sub new
  201. {
  202.  my ($class,$w,%args) = @_;
  203.  my $t = $w->toplevel;
  204.  $args{'widget'} = $w;
  205.  if (exists $args{'-droptypes'})
  206.   {
  207.    # Convert single type to array-of-one
  208.    $args{'-droptypes'} = [$args{'-droptypes'}] unless (ref $args{'-droptypes'});
  209.   }
  210.  else
  211.   {
  212.    # Default to all known types.
  213.    $args{'-droptypes'} = \@types;
  214.   }
  215.  my ($key,$val);
  216.  while (($key,$val) = each %args)
  217.   {
  218.    if ($key =~ /command$/)
  219.     {
  220.      $val = Tk::Callback->new($val);
  221.      $args{$key} = $val;
  222.     }
  223.   }
  224.  my $obj = bless \%args,$class;
  225.  unless (exists $t->{'DropSites'})
  226.   {
  227.    $t->{'DropSites'} = {};
  228.    $t->{'DropUpdate'} = 0;
  229.   }
  230.  my $type;
  231.  foreach $type (@{$args{'-droptypes'}})
  232.   {
  233.    Tk::DropSite->import($type) unless (exists $type{$type});
  234.    my $class = $type{$type};
  235.    $class->InitSite($obj);
  236.    # Should this be indexed by type or class ?
  237.    unless (exists $t->{'DropSites'}->{$type})
  238.     {
  239.      $t->{'DropSites'}->{$type}  = [];
  240.     }
  241.    push(@{$t->{'DropSites'}->{$type}},$obj);
  242.   }
  243.  $w->OnDestroy([$obj,'delete']);
  244.  $obj->DropSiteUpdate;
  245.  $w->bindtags([$w->bindtags,$obj]);
  246.  $w->Tk::bind($obj,'<Map>',[$obj,'DropSiteUpdate']);
  247.  $w->Tk::bind($obj,'<Unmap>',[$obj,'DropSiteUpdate']);
  248.  $w->Tk::bind($obj,'<Configure>',[$obj,'DropSiteUpdate']);
  249.  $t->Tk::bind($class,'<Configure>',[\&TopSiteUpdate,$t]);
  250.  unless (grep($_ eq $class,$t->bindtags))
  251.   {
  252.    $t->bindtags([$t->bindtags,$class]);
  253.   }
  254.  return $obj;
  255. }
  256.  
  257. 1;
  258.