Advertisement
Guest User

squentin

a guest
Nov 15th, 2008
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 16.17 KB | None | 0 0
  1. #!/bin/perl
  2. # usage : find ~/Pictures/ -iname \*.jpg | perl standalone_mosaic.pl
  3. use strict;
  4. use warnings;
  5. use Gtk2 "-init";
  6.  
  7. my %PixCache;
  8.  
  9. #my $path=$ARGV[0]||$ENV{PWD};
  10. my @list;
  11. while (<>)
  12. {   chomp;
  13.     push @list,$_;
  14. }
  15. warn "$#list files\n";
  16.  
  17. my $window=Gtk2::Window->new;
  18. my $vscroll=Gtk2::VScrollbar->new;
  19. my $mosaic=Mosaic->new(\&select,\&get_data,\&makepixbuf,\&activate,\&menupopup,$vscroll);
  20. my $hbox=Gtk2::HBox->new;
  21. $hbox->pack_start($mosaic,1,1,2);
  22. $hbox->pack_start($vscroll,0,0,2);
  23. $window->add($hbox);
  24. $window ->signal_connect( destroy => sub { exit } );
  25. $window->set_size_request(500,500);
  26. $window->show_all;
  27.  
  28.  
  29. Gtk2->main;
  30.  
  31. sub get_data
  32. {   #opendir my($dh),$path;
  33.     #my @l=map "$path/$_", grep m/\.jpg$/i, readdir $dh;
  34.     #closedir $dh;
  35.     #return \@l;
  36.     return \@list;
  37. }
  38.  
  39. sub select
  40. {   warn "select @_\n";
  41. }
  42. sub activate
  43. {   warn "activate @_\n";
  44.     system "gqview -t \Q$_[0]\E &";
  45.     #system "qiv -t \Q$_[0]\E &";
  46. }
  47.  
  48. sub menupopup
  49. {   warn "menu @_\n"
  50. }
  51.  
  52. sub makepixbuf  #use a very simple cache, could be improved
  53. {   my ($key,$width,$height)=@_;
  54.     my $pixbuf=$PixCache{$key};
  55.     my $purge;
  56.     unless ($pixbuf)
  57.     {   if (defined $width)
  58.         {   $pixbuf=$PixCache{$key}= eval { Gtk2::Gdk::Pixbuf->new_from_file_at_scale($key, $width, $height,1) };
  59.             unless ($pixbuf) {delete $PixCache{$key};return undef;}
  60.             $purge=1 if keys %PixCache >120;
  61.         }
  62.         else {return undef;}
  63.     }
  64.     $pixbuf->{lastuse}=time;
  65.     if ($purge) #should be done in an idle
  66.     {   my $nb= keys(%PixCache)-100;
  67.         delete $PixCache{$_} for (sort {$PixCache{$a}{lastuse} <=> $PixCache{$b}{lastuse}} keys %PixCache)[0..$nb];
  68.     }
  69.     return $pixbuf;
  70. }
  71.  
  72. package Mosaic;
  73. use Gtk2;
  74. use base 'Gtk2::DrawingArea';
  75.  
  76. use constant
  77. {   XPAD => 2,  YPAD => 2,
  78.     TRUE => 1,  FALSE =>0,
  79. };
  80.  
  81. sub new
  82. {   my ($class,$selectsub,$getdatasub,$makepixbufsub,$activatesub,$menupopupsub,$vscroll)=@_;
  83.     my $self = bless Gtk2::DrawingArea->new, $class;
  84.     $self->can_focus(TRUE);
  85.     $self->add_events([qw/button_press_mask button_release_mask pointer-motion-mask leave-notify-mask/]);
  86.     $self->{vscroll}=$vscroll;
  87.     #$vscroll->get_adjustment->signal_connect(value_changed => sub {$self->queue_draw});
  88.     $vscroll->get_adjustment->signal_connect(value_changed => \&after_scroll,$self);
  89.     $self->signal_connect(scroll_event  => \&scroll_event_cb);
  90.     $self->signal_connect(expose_event  => \&expose_cb);
  91.     $self->signal_connect(focus_out_event   => \&focus_change);
  92.     $self->signal_connect(focus_in_event    => \&focus_change);
  93.     $self->signal_connect(configure_event   => \&configure_cb);
  94.     $self->signal_connect(drag_begin    => \&drag_begin_cb);
  95.     $self->signal_connect(button_press_event=> \&button_press_cb);
  96.     $self->signal_connect(button_release_event=> \&button_release_cb);
  97.     $self->signal_connect(key_press_event   => \&key_press_cb);
  98.     $self->signal_connect(realize   => sub { $_[0]->Fill });
  99.     #$self->signal_connect(motion_notify_event=> \&start_tooltip);
  100.     #$self->signal_connect(leave_notify_event=> \&abort_tooltip);
  101.     $self->{selectsub}=$selectsub;
  102.     $self->{get_fill_data_sub}=$getdatasub;
  103.     $self->{activatesub}=$activatesub;
  104.     $self->{menupopupsub}=$menupopupsub;
  105.     $self->{makepixbuf}=$makepixbufsub;
  106.     return $self;
  107. }
  108.  
  109. sub get_selected
  110. {   sort keys %{$_[0]{selected}};
  111. }
  112. sub reset_selection
  113. {   $_[0]{selected}={};
  114.     $_[0]{lastclick}=undef;
  115.     $_[0]{startgrow}=undef;
  116. }
  117. sub drag_begin_cb
  118. {   $_[0]->{pressed}=undef;
  119. }
  120. sub button_press_cb
  121. {   my ($self,$event)=@_;
  122.     $self->grab_focus;
  123.     my $but=$event->button;
  124.     my $selected=$self->{selected};
  125.     if ($but==1 && $event->type eq '2button-press')
  126.     {   $self->{activatesub}->(keys %$selected);
  127.         return 1;
  128.     }
  129.     if ($but==1)
  130.     {   my ($i,$j,$key)=$self->coord_to_index($event->get_coords);
  131.         return 0 unless defined $j;
  132.         if ( $event->get_state * ['shift-mask', 'control-mask'] || !exists $selected->{$key} )
  133.             { $self->key_selected($event,$i,$j);}
  134.         else    { $self->{pressed}=1; }
  135.         return 0;
  136.     }
  137.     if ($but==3)
  138.     {   my ($i,$j,$key)=$self->coord_to_index($event->get_coords);
  139.         if (defined $key && !exists $selected->{$key})
  140.         {   $self->key_selected($event,$i,$j);
  141.         }
  142.         $self->{menupopupsub}->($event,[keys %$selected]);
  143.         return 1;
  144.     }
  145.     1;
  146. }
  147. sub button_release_cb
  148. {   my ($self,$event)=@_;
  149.     return 0 unless $event->button==1 && $self->{pressed};
  150.     $self->{pressed}=undef;
  151.     my ($i,$j)=$self->coord_to_index($event->get_coords);
  152.     return 0 unless defined $j;
  153.     $self->key_selected($event,$i,$j);
  154.     return 1;
  155. }
  156.  
  157. sub Fill
  158. {   my ($self,$samelist)=@_;
  159.     my $list=$self->{list};
  160.     $self->{list}=$list= $self->{get_fill_data_sub}->() unless $samelist;
  161.     my $window=$self->window;
  162.  
  163.     #unless ($window) { $self->{delayed}||=Glib::Timeout->add(200,\&Fill,$self); warn 2; return 1 }
  164.     #Glib::Source->remove( $self->{delayed} ) if $self->{delayed};warn 3;
  165.     #delete $self->{delayed};
  166.  
  167.     my ($width,$height)=$window->get_size;
  168.     $self->{width}=$width;#warn "$self : filling with width=$width\n";
  169.  
  170.     $self->{hsize}=64;
  171.     $self->{vsize}=128;
  172.  
  173.     my $nw= int($width / ($self->{hsize}+2*XPAD)) || 1;
  174.     my $nh= int(@$list/$nw);
  175.     my $nwlast= @$list % $nw;
  176.     $nh++ if $nwlast;
  177.     $nwlast=$nw unless $nwlast;
  178.     $self->{dim}=[$nw,$nh,$nwlast];
  179.     #$self->set_size_request(-1,$nh*($self->{vsize}+2*YPAD));
  180.     $self->{maxy}= $nh*($self->{vsize}+2*YPAD);
  181.     $self->{viewwindowsize}=[$self->window->get_size];
  182.     $self->update_scrollbar;
  183.     $self->queue_draw;
  184.     #$self->start_tooltip;
  185. }
  186. sub update_scrollbar
  187. {   my $self=$_[0];
  188.     my $scroll= $self->{vscroll};
  189.     my $pagesize=$self->{viewwindowsize}[1]||0;
  190.     my $upper=$self->{maxy}||0;
  191.     my $adj=$scroll->get_adjustment;
  192.     my $oldpos= $adj->upper ? ($adj->page_size/2+$adj->value) / $adj->upper : 0;
  193.     $adj->page_size($pagesize);
  194.     if ($upper>$pagesize)   {$scroll->show; $adj->upper($upper); $scroll->queue_draw; }
  195.     else            {$scroll->hide; $adj->upper(0);}
  196.     $adj->step_increment($pagesize*.125);
  197.     $adj->page_increment($pagesize*.75);
  198.     my $newval= $oldpos*$adj->upper - $adj->page_size/2;
  199.     $newval=$adj->upper-$pagesize if $newval > $adj->upper-$pagesize;
  200.     $adj->set_value($newval);
  201. }
  202. sub scroll_event_cb
  203. {   my ($self,$event,$pageinc)=@_;
  204.     my $dir= ref $event ? $event->direction : $event;
  205.     $dir= $dir eq 'up' ? -1 : $dir eq 'down' ? 1 : 0;
  206.     return unless $dir;
  207.     my $adj=$self->{vscroll}->get_adjustment;
  208.     my $max= $adj->upper - $adj->page_size;
  209.     my $value= $adj->value + $dir* ($pageinc? $adj->page_increment : $adj->step_increment);
  210.     $value=$max if $value>$max;
  211.     $value=0 if $value<0;
  212.     $adj->set_value($value);
  213.     1;
  214. }
  215.  
  216. sub after_scroll
  217. {   my ($adj,$self)=@_;
  218.     my $new=int $adj->value;
  219.     my $old=$self->{lastdy};
  220.     return unless defined $old;
  221.     return if $new==$old;
  222.     $self->{lastdy}=$new;
  223.     $self->window->scroll(0,$old-$new);
  224. }
  225.  
  226. #sub show_tooltip
  227. #{  my $self=$_[0];
  228. #   Glib::Source->remove(delete $self->{tooltip_t}) if $self->{tooltip_t};
  229. #   $self->{tooltip_t}=Glib::Timeout->add(5000, \&abort_tooltip,$self);
  230. #
  231. #   my ($window,$px,$py)=Gtk2::Gdk::Display->get_default->get_window_at_pointer;
  232. #   return 0 unless $window && $window==$self->window;
  233. #   my ($i,$j,$key)=$self->coord_to_index($px,$py);
  234. #   return 0 unless defined $key;
  235. #   my $win=$self->{tooltip_w}=Gtk2::Window->new('popup');
  236. #   #$win->{key}=$key;
  237. #   #$win->set_border_width(3);
  238. #   my $label=Gtk2::Label->new;
  239. #   $label->set_markup(::ReplaceAAFields($key,"<b>%a</b>%Y\n<small>%s <small>%l</small></small>",$self->{col},1));
  240. #   my $request=$label->size_request;
  241. #   my ($x,$y,$w,$h)=$self->index_to_rect($i,$j);
  242. #   my ($rx,$ry)=$self->window->get_origin;
  243. #   $x+= $rx + $w/2 - $request->width/2;
  244. #   $y+= $ry + $h+YPAD+1;
  245. #
  246. #   my $screen=$self->get_screen;
  247. #   my $monitor=$screen->get_monitor_at_window($self->window);
  248. #   my (undef,undef,$xmax,$ymax)=$screen->get_monitor_geometry($monitor)->values;
  249. #   $xmax-=$request->width;
  250. #   $ymax-=$request->height;
  251. #   $x=$xmax if $x>$xmax;
  252. #   $y-=$h+$request->height if $y>$ymax;
  253. #
  254. #   my $frame=Gtk2::Frame->new;
  255. #   $frame->add($label);
  256. #   $win->add($frame);
  257. #   $win->move($x,$y);
  258. #   $win->show_all;
  259. #   return 0;
  260. #}
  261.  
  262. #sub start_tooltip
  263. #{  my ($self,$event)=@_;
  264. #   my $timeout= $self->{tooltip_browsemode} ? 100 : 1000;
  265. #   $self->abort_tooltip;
  266. #   $self->{tooltip_t}=Glib::Timeout->add($timeout, \&show_tooltip,$self);
  267. #   return 0;
  268. #}
  269. #sub abort_tooltip
  270. #{  my $self=$_[0];
  271. #   Glib::Source->remove(delete $self->{tooltip_t}) if $self->{tooltip_t};
  272. #   if ($self->{tooltip_w})
  273. #   {   $self->{tooltip_browsemode}=1;
  274. #       Glib::Source->remove($self->{tooltip_t2}) if $self->{tooltip_t2};
  275. #       $self->{tooltip_t2}=Glib::Timeout->add(500, sub{$_[0]{tooltip_browsemode}=$_[0]{tooltip_t2}=0;} ,$self);
  276. #       $self->{tooltip_w}->destroy;
  277. #   }
  278. #   $self->{tooltip_w}=undef;
  279. #   0;
  280. #}
  281.  
  282. sub configure_cb
  283. {   my ($self,$event)=@_;
  284.     return unless $self->{width};
  285.     $self->{viewwindowsize}=[$event->width,$event->height];
  286.     my $iw= $self->{hsize}+2*XPAD;
  287.     if ( int($self->{width}/$iw) == int($event->width/$iw))
  288.     {   $self->update_scrollbar;
  289.         return;
  290.     }
  291.     $self->reset;
  292.     $self->Fill(1);
  293. }
  294.  
  295. sub expose_cb
  296. {   my ($self,$event)=@_;
  297.     my ($exp_x1,$exp_y1,$exp_x2,$exp_y2)=$event->area->values;
  298.     $exp_x2+=$exp_x1; $exp_y2+=$exp_y1;
  299.     my $dy=int $self->{vscroll}->get_adjustment->value;
  300.     #$self->start_tooltip if exists $self->{lastdy} && $self->{lastdy}!=$dy;
  301.     $self->{lastdy}=$dy;
  302.     my $window=$self->window;
  303.     my $style=$self->get_style;
  304.     #my ($width,$height)=$window->get_size;
  305.     #warn "expose_cb : $width,$height\n";
  306.     my $state= $self->state eq 'insensitive' ? 'insensitive' : 'normal';
  307.     my $sstate=$self->has_focus ? 'selected' : 'active';
  308.     #my $gc= $style->text_gc($state);
  309.     my $bgc= $style->base_gc($state);
  310.     #my $sgc= $style->text_gc($sstate);
  311.     my $sbgc= $style->base_gc($sstate);
  312. #   $window->draw_rectangle($bgc,TRUE,$event->area->values); #clear the area with the base bg color
  313.     #$style->paint_flat_box( $window,$state,'none',$event->area,$self,'',$event->area->values);
  314.  
  315.     return unless $self->{list};
  316.     my ($nw,$nh,$nwlast)=@{$self->{dim}};
  317.     my $list=$self->{list};
  318.     my $vsize=$self->{vsize};
  319.     my $hsize=$self->{hsize};
  320.     my $i1=int($exp_x1/($hsize+2*XPAD));
  321.     my $i2=int($exp_x2/($hsize+2*XPAD));
  322.     my $j1=int(($dy+$exp_y1)/($vsize+2*YPAD));
  323.     my $j2=int(($dy+$exp_y2)/($vsize+2*YPAD));
  324.     $i2=$nw-1 if $i2>=$nw;
  325.     $j2=$nh-1 if $j2>=$nh;
  326.     for my $j ($j1..$j2)
  327.     {   my $y=$j*($vsize+2*YPAD)+YPAD - $dy;  #warn "j=$j y=$y\n";
  328.         $i2=$nwlast-1 if $j==$nh-1;
  329.         for my $i ($i1..$i2)
  330.         {   my $pos=$i+$j*$nw;
  331.             #last if $pos>$#$list;
  332.             my $key=$list->[$pos];
  333.             my $x=$i*($hsize+2*XPAD)+XPAD;
  334.             my $state=$state;
  335.             if (exists $self->{selected}{$key})
  336.             {   $window->draw_rectangle($sbgc,1,$x-XPAD(),$y-YPAD(),$hsize+XPAD*2,$vsize+YPAD*2);
  337.                 #$state=$sstate;
  338.                 #$style->paint_flat_box( $window,$state,'none',$event->area,$self,'',
  339.                 #           $x-XPAD(),$y-YPAD(),$hsize+XPAD*2,$vsize+YPAD*2 );
  340.             }
  341.             #$window->draw_rectangle($style->text_gc($state),1,$x+20,$y+20,24,24); #DEBUG
  342.             my $pixbuf= $self->{makepixbuf}->($key);
  343.             if ($pixbuf) { $self->drawpic($x,$y,$pixbuf) }
  344.             #elsif (defined $pixbuf)
  345.             else
  346.             {   #warn "add idle\n" unless $self->{idle};
  347.                 $self->{idle}||=Glib::Idle->add(\&idle,$self);
  348.                 $self->{window}||=$window;
  349.                 $self->{queue}{$i+$j*$nw}=[$x,$y+$dy,$key];
  350.             }
  351. #           else
  352. #           {   my $layout=Gtk2::Pango::Layout->new( $self->create_pango_context );
  353. #               #$layout->set_text($key);
  354. #               $layout->set_markup('<small>'.Glib::Markup::escape_text($key).'</small>');
  355. #               $layout->set_wrap('word-char');
  356. #               $layout->set_width($hsize * Gtk2::Pango->scale);
  357. #               $layout->set_height($vsize * Gtk2::Pango->scale);
  358. #               $layout->set_ellipsize('end');
  359. #               $style->paint_layout($window, $state, 1,
  360. #                   Gtk2::Gdk::Rectangle->new($x,$y,$hsize,$vsize), $self, undef, $x, $y, $layout);
  361. #           }
  362.         }
  363.     }
  364.     1;
  365. }
  366.  
  367. sub focus_change
  368. {   my $self=$_[0];
  369.     #$self->queue_draw;
  370.     $self->redraw_keys($self->{selected});
  371.     1;
  372. }
  373.  
  374. sub coord_to_index
  375. {   my ($self,$x,$y)=@_;
  376.     $y+=int $self->{vscroll}->get_adjustment->value;
  377.     my ($nw,$nh,$nwlast)=@{$self->{dim}};
  378.     my $i=int($x/($self->{hsize}+2*XPAD));
  379.     return undef if $i>=$nw;
  380.     my $j=int($y/($self->{vsize}+2*YPAD));
  381.     return undef if $j>=$nh;
  382.     return undef if $j==$nh-1 && $i>=$nwlast;
  383.     my $key=$self->{list}[$i+$j*$nw];
  384.     return $i,$j,$key;
  385. }
  386. sub index_to_rect
  387. {   my ($self,$i,$j)=@_;
  388.     my $x=$i*($self->{hsize}+2*XPAD)+XPAD;
  389.     my $y=$j*($self->{vsize}+2*YPAD)+YPAD;
  390.     $y-=int $self->{vscroll}->get_adjustment->value;
  391.     return $x,$y,$self->{hsize},$self->{vsize};
  392. }
  393.  
  394. sub redraw_keys
  395. {   my ($self,$keyhash)=@_;#Gtk2::Gdk::Window->set_debug_updates(1);
  396.     return unless keys %$keyhash;
  397.     my $hsize2=$self->{hsize}+2*XPAD;
  398.     my $vsize2=$self->{vsize}+2*YPAD;
  399.     my $y=int $self->{vscroll}->get_adjustment->value;
  400.     my ($nw,$nh,$nwlast)=@{$self->{dim}};
  401.     my $height= $self->{viewwindowsize}[1];
  402.     my $j1=int($y/($self->{vsize}+2*YPAD));
  403.     my $j2=int(($y+$height)/($self->{vsize}+2*YPAD));
  404.     for my $j ($j1..$j2)
  405.     {   for my $i (0..$nw-1)
  406.         {   my $key=$self->{list}[$i+$j*$nw];
  407.             next unless defined $key;
  408.             next unless exists $keyhash->{$key};
  409.             $self->queue_draw_area($i*$hsize2,$j*$vsize2-$y,$hsize2,$vsize2);
  410.         }
  411.     }
  412. }
  413.  
  414. sub key_selected
  415. {   my ($self,$event,$i,$j)=@_;
  416.     $self->scroll_to_row($j);
  417.     my ($nw)=@{$self->{dim}};
  418.     my $list=$self->{list};
  419.     my $pos=$i+$j*$nw;
  420.     my $key=$list->[$pos];
  421.     my %changed;
  422.     $changed{$_}=1 for keys %{$self->{selected}};
  423.     unless ($event->get_state >= ['control-mask'])
  424.     {   $self->{selected}={};
  425.     }
  426.     if ($event->get_state >= ['shift-mask'] && defined $self->{lastclick})
  427.     {   $self->{startgrow}=$self->{lastclick} unless defined $self->{startgrow};
  428.         my $i1=$self->{startgrow};
  429.         my $i2=$pos;
  430.         ($i1,$i2)=($i2,$i1) if $i1>$i2;
  431.         $self->{selected}{ $list->[$_] }=undef for $i1..$i2;
  432.     }
  433.     elsif (exists $self->{selected}{$key})
  434.     {   delete $self->{selected}{$key};
  435.         delete $self->{startgrow};
  436.     }
  437.     else
  438.     {   $self->{selected}{$key}=undef;
  439.         delete $self->{startgrow};
  440.     }
  441.     $self->{lastclick}=$pos;
  442.     $changed{$_}-- for keys %{$self->{selected}};
  443.     $changed{$_} or delete $changed{$_} for keys %changed;
  444.     $self->redraw_keys(\%changed);
  445.     #$self->queue_draw;
  446.     $self->{selectsub}->([keys %{$self->{selected}}]);
  447. }
  448.  
  449. sub scroll_to_row
  450. {   my ($self,$j)=@_;
  451.     my $y1=$j*($self->{vsize}+2*YPAD)+YPAD;
  452.     my $y2=$y1+$self->{vsize};
  453.     $self->{vscroll}->get_adjustment->clamp_page($y1,$y2);
  454. }
  455.  
  456. sub key_press_cb
  457. {   my ($self,$event)=@_;
  458.     my $key=Gtk2::Gdk->keyval_name( $event->keyval );
  459.     if ( $key eq 'space' || $key eq 'Return' )
  460.     {   &{ $self->{activatesub} }($self);
  461.         return 1;
  462.     }
  463.     my $pos=0;
  464.     $pos=$self->{lastclick} if $self->{lastclick};
  465.     my ($nw,$nh,$nwlast)=@{$self->{dim}};
  466.     my $page= int($self->{vscroll}->get_adjustment->page_size / ($self->{vsize}+2*YPAD));
  467.     my $i=$pos % $nw;
  468.     my $j=int($pos/$nw);
  469.     if  ($key eq 'Left')    {$i--}
  470.     elsif   ($key eq 'Right')   {$i++}
  471.     elsif   ($key eq 'Up')      {$j--}
  472.     elsif   ($key eq 'Down')    {$j++}
  473.     elsif   ($key eq 'Home')    {$i=$j=0; }
  474.     elsif   ($key eq 'End')     {$i=$nwlast-1; $j=$nh-1;}
  475.     elsif   ($key eq 'Page_Up') { $j-=$page; }
  476.     elsif   ($key eq 'Page_Down')   { $j+=$page; }
  477.     else {return 0}
  478.     if  ($i<0)      {$j--; $i= $j<0 ? 0 : $nw-1}
  479.     elsif   ($i>=$nw)   {$j++; $i= $j>=$nh ? $nwlast-1 : 0 }
  480.     if  ($j<0)      {$j=0;$i=0}
  481.     elsif   ($j>=$nh-1) {$j=$nh-1; $i=$nwlast-1 }
  482.     $self->key_selected($event,$i,$j);
  483.     return 1;
  484. }
  485.  
  486. sub reset
  487. {   my $self=$_[0];
  488.     #delete $self->{list};
  489.     delete $self->{queue};
  490.     Glib::Source->remove( $self->{idle} ) if $self->{idle};
  491.     delete $self->{idle};
  492. }
  493.  
  494. sub idle
  495. {   my $self=$_[0];#warn " ...idle...\n";
  496.     {   last unless $self->{queue} && $self->mapped;
  497.         my ($y,$ref)=each %{ $self->{queue} };
  498.         last unless $ref;
  499.         delete $self->{queue}{$y};
  500.         $self->delayed_draw(@$ref);
  501.         last unless scalar keys %{ $self->{queue} };
  502.         return 1;
  503.     }
  504.     delete $self->{queue};
  505.     delete $self->{window};#warn "...idle END\n";
  506.     return $self->{idle}=undef;
  507. }
  508.  
  509. sub delayed_draw
  510. {   my ($self,$x,$y,$key)=@_;
  511.     my $vadj=$self->{vscroll}->get_adjustment;
  512.     my $dy=int $vadj->get_value;
  513.     my $page=$vadj->page_size;
  514.     return if $dy > $y+$self->{vsize} || $dy+$page < $y; #no longer visible
  515.     my $pixbuf= $self->{makepixbuf}->($key,$self->{hsize},$self->{vsize});
  516.     $self->drawpic($x,$y-$dy,$pixbuf) if $pixbuf;
  517. }
  518.  
  519. sub drawpic
  520. {   my ($self,$x,$y,$pixbuf)=@_;
  521.     my $offy=int(($self->{vsize}-$pixbuf->get_height)/2);#center pic
  522.     my $offx=int(($self->{hsize}-$pixbuf->get_width )/2);
  523.     my $window=$self->window;
  524.     my $gc=Gtk2::Gdk::GC->new($window);
  525.     $window->draw_pixbuf( $gc, $pixbuf,0,0, $x+$offx, $y+$offy,-1,-1,'none',0,0);
  526. }
  527.  
  528.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement