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

  1. package Tk::ProgressBar;
  2.  
  3. use vars qw($VERSION);
  4. $VERSION = sprintf '4.%03d', q$Revision: #10 $ =~ /\D(\d+)\s*$/;
  5.  
  6. use Tk;
  7. use Tk::Canvas;
  8. use Tk::Trace;
  9. use Carp;
  10. use strict;
  11.  
  12. use base qw(Tk::Derived Tk::Canvas);
  13.  
  14. Construct Tk::Widget 'ProgressBar';
  15.  
  16. sub ClassInit {
  17.     my ($class,$mw) = @_;
  18.  
  19.     $class->SUPER::ClassInit($mw);
  20.  
  21.     $mw->bind($class,'<Configure>', ['_layoutRequest',1]);
  22. }
  23.  
  24.  
  25. sub Populate {
  26.     my($c,$args) = @_;
  27.  
  28.     $c->ConfigSpecs(
  29.     -width    => [PASSIVE => undef, undef, 0],
  30.     '-length' => [PASSIVE => undef, undef, 0],
  31.     -from      => [PASSIVE => undef, undef, 0],
  32.     -to      => [PASSIVE => undef, undef, 100],
  33.     -blocks   => [PASSIVE => undef, undef, 10],
  34.     -padx     => [PASSIVE => 'padX', 'Pad', 0],
  35.     -pady     => [PASSIVE => 'padY', 'Pad', 0],
  36.     -gap      => [PASSIVE => undef, undef, 1],
  37.     -colors   => [PASSIVE => undef, undef, undef],
  38.     -relief      => [SELF => 'relief', 'Relief', 'sunken'],
  39.     -value    => [METHOD  => undef, undef, undef],
  40.     -variable => [METHOD  => undef, undef, undef],
  41.     -anchor   => [METHOD  => 'anchor', 'Anchor', 'w'],
  42.     -resolution
  43.           => [PASSIVE => undef, undef, 1.0],
  44.     -highlightthickness
  45.           => [SELF => 'highlightThickness','HighlightThickness',0],
  46.     -troughcolor
  47.           => [PASSIVE => 'troughColor', 'Background', 'grey55'],
  48.     );
  49.     _layoutRequest($c,1);
  50.     $c->OnDestroy(['Destroyed' => $c]);
  51. }
  52.  
  53. sub anchor {
  54.     my $c = shift;
  55.     my $var = \$c->{Configure}{'-anchor'};
  56.     my $old = $$var;
  57.  
  58.     if(@_) {
  59.     my $new = shift;
  60.     croak "bad anchor position \"$new\": must be n, s, w or e"
  61.         unless $new =~ /^[news]$/;
  62.     $$var = $new;
  63.     }
  64.  
  65.     $old;
  66. }
  67.  
  68. sub _layoutRequest {
  69.     my $c = shift;
  70.     my $why = shift;
  71.     $c->afterIdle(['_arrange',$c]) unless $c->{'layout_pending'};
  72.     $c->{'layout_pending'} |= $why;
  73. }
  74.  
  75. sub _arrange {
  76.     my $c = shift;
  77.     my $why = $c->{'layout_pending'};
  78.  
  79.     $c->{'layout_pending'} = 0;
  80.  
  81.     my $w = $c->Width;
  82.     my $h = $c->Height;
  83.     my $bw = $c->cget('-borderwidth') + $c->cget('-highlightthickness');
  84.     my $x = abs(int($c->{Configure}{'-padx'})) + $bw;
  85.     my $y = abs(int($c->{Configure}{'-pady'})) + $bw;
  86.     my $value = $c->value;
  87.     my $from = $c->{Configure}{'-from'};
  88.     my $to   = $c->{Configure}{'-to'};
  89.     my $horz = $c->{Configure}{'-anchor'} =~ /[ew]/i ? 1 : 0;
  90.     my $dir  = $c->{Configure}{'-anchor'} =~ /[se]/i ? -1 : 1;
  91.  
  92.     my($minv,$maxv) = $from < $to ? ($from,$to) : ($to,$from);
  93.  
  94.     if($w == 1 && $h == 1) {
  95.     my $bw = $c->cget('-borderwidth');
  96.     my $defw = 10 + $y*2 + $bw *2;
  97.     my $defl = ($maxv - $minv) + $x*2 + $bw*2;
  98.  
  99.     $h = $c->pixels($c->{Configure}{'-length'}) || $defl;
  100.     $w = $c->pixels($c->{Configure}{'-width'})  || $defw;
  101.  
  102.     ($w,$h) = ($h,$w) if $horz;
  103.     $c->GeometryRequest($w,$h);
  104.     $c->parent->update;
  105.     $c->update;
  106.  
  107.     $w = $c->Width;
  108.     $h = $c->Height;
  109.     }
  110.  
  111.     $w -= $x*2;
  112.     $h -= $y*2;
  113.  
  114.     my $length = $horz ? $w : $h;
  115.     my $width  = $horz ? $h : $w;
  116.  
  117.     my $blocks = int($c->{Configure}{'-blocks'});
  118.     my $gap    = int($c->{Configure}{'-gap'});
  119.  
  120.     $blocks = 1 if $blocks < 1;
  121.  
  122.     my $gwidth = $gap * ( $blocks - 1);
  123.     my $bwidth = ($length - $gwidth) / $blocks;
  124.  
  125.     if($bwidth < 3 || $blocks <= 1 || $gap <= 0) {
  126.     $blocks = 1;
  127.     $bwidth = $length;
  128.     $gap = 0;
  129.     }
  130.  
  131.     if($why & 1) {
  132.     my $colors = $c->{Configure}{'-colors'} || [];
  133.     my $bdir = $from < $to ? $dir : 0 - $dir;
  134.  
  135.     $c->delete($c->find('all'));
  136.  
  137.     $c->createRectangle(0,0,$w+$x*2,$h+$y*2,
  138.         -fill =>  $c->{Configure}{'-troughcolor'},
  139.         -width => 0,
  140.         -outline => undef);
  141.  
  142.     $c->{'cover'} =    $c->createRectangle($x,$y,$w,$h,
  143.         -fill =>  $c->{Configure}{'-troughcolor'},
  144.         -width => 0,
  145.         -outline => undef);
  146.  
  147.     my($x0,$y0,$x1,$y1);
  148.  
  149.     if($horz) {
  150.         if($bdir > 0) {
  151.         ($x0,$y0) = ($x - $gap,$y);
  152.         }
  153.         else {
  154.         ($x0,$y0) = ($length + $x + $gap,$y);
  155.         }
  156.         ($x1,$y1) = ($x0,$y0 + $width);
  157.     }
  158.     else {
  159.         if($bdir > 0) {
  160.         ($x0,$y0) = ($x,$y - $gap);
  161.         }
  162.         else {
  163.         ($x0,$y0) = ($x,$length + $y + $gap);
  164.         }
  165.         ($x1,$y1) = ($x0 + $width,$y0);
  166.     }
  167.  
  168.     my $blks  = $blocks;
  169.     my $dval  = ($maxv - $minv) / $blocks;
  170.     my $color = $c->cget('-foreground');
  171.     my $pos   = 0;
  172.     my $val   = $minv;
  173.  
  174.     while($val < $maxv) {
  175.         my($bw,$nval);
  176.  
  177.         while(($pos < @$colors) && $colors->[$pos] <= $val) {
  178.         $color = $colors->[$pos+1];
  179.         $pos += 2;
  180.         }
  181.  
  182.         if($blocks == 1) {
  183.         $nval = defined($colors->[$pos])
  184.             ? $colors->[$pos] : $maxv;
  185.         $bw = (($nval - $val) / ($maxv - $minv)) * $length;
  186.         }
  187.         else {
  188.         $bw = $bwidth;
  189.         $nval = $val + $dval if($blocks > 1);
  190.         }
  191.  
  192.         if($horz) {
  193.         if($bdir > 0) {
  194.             $x0 = $x1 + $gap;
  195.             $x1 = $x0 + $bw;
  196.         }
  197.         else {
  198.             $x1 = $x0 - $gap;
  199.             $x0 = $x1 - $bw;
  200.         }
  201.         }
  202.         else {
  203.         if($bdir > 0) {
  204.             $y0 = $y1 + $gap;
  205.             $y1 = $y0 + $bw;
  206.         }
  207.         else {
  208.             $y1 = $y0 - $gap;
  209.             $y0 = $y1 - $bw;
  210.         }
  211.         }
  212.  
  213.         $c->createRectangle($x0,$y0,$x1,$y1,
  214.         -fill => $color,
  215.         -width => 0,
  216.         -outline => undef
  217.         );
  218.         $val = $nval;
  219.     }
  220.     }
  221.  
  222.     my $cover = $c->{'cover'};
  223.     my $ddir = $from > $to ? 1 : -1;
  224.  
  225.     if(($value <=> $to) == (0-$ddir)) {
  226.     $c->lower($cover);
  227.     }
  228.     elsif(($value <=> $from) == $ddir) {
  229.     $c->raise($cover);
  230.     my $x1 = $horz ? $x + $length : $x + $width;
  231.     my $y1 = $horz ? $y + $width : $y + $length;
  232.     $c->coords($cover,$x,$y,$x1,$y1);
  233.     }
  234.     else {
  235.     my $step;
  236.     $value = int($value / $step) * $step
  237.         if(defined($step = $c->{Configure}{'-resolution'}) && $step > 0);
  238.  
  239.     $maxv = $minv+1
  240.         if $minv == $maxv;
  241.  
  242.     my $range = $maxv - $minv;
  243.     my $bval = $range / $blocks;
  244.     my $offset = abs($value - $from);
  245.     my $ioff = int($offset / $bval);
  246.     my $start = $ioff * ($bwidth + $gap);
  247.     $start += ($offset - ($ioff * $bval)) / $bval * $bwidth;
  248.  
  249.     my($x0,$x1,$y0,$y1);
  250.  
  251.     if($horz) {
  252.         $y0 = $y;
  253.         $y1 = $y + $h;
  254.         if($dir > 0) {
  255.         $x0 = $x + $start;
  256.         $x1 = $x + $w;
  257.         }
  258.         else {
  259.         $x0 = $x;
  260.         $x1 = $w + $x - $start;
  261.         }
  262.     }
  263.     else {
  264.         $x0 = $x;
  265.         $x1 = $x + $w;
  266.         if($dir > 0) {
  267.         $y0 = $y + $start;
  268.         $y1 = $y + $h;
  269.         }
  270.         else {
  271.         $y0 = $y;
  272.         $y1 = $h + $y - $start;
  273.         }
  274.     }
  275.  
  276.  
  277.     $c->raise($cover);
  278.     $c->coords($cover,$x0,$y0,$x1,$y1);
  279.     }
  280. }
  281.  
  282. sub value {
  283.     my $c = shift;
  284.     my $val = defined($c->{'-variable'})
  285.         ? $c->{'-variable'}
  286.         : \$c->{'-value'};
  287.     my $old = defined($$val) ? $$val : $c->{Configure}{'-from'};
  288.  
  289.     if(@_) {
  290.     my $value = shift;
  291.     $$val = defined($value) ? $value : $c->{Configure}{'-from'};
  292.     _layoutRequest($c,2);
  293.     }
  294.  
  295.     $old;
  296. }
  297.  
  298. sub variable {
  299.     my $c = shift;
  300.     my $oldvarref = $c->{'-variable'};
  301.     my $oldval = $$oldvarref if $oldvarref;
  302.     if(@_) {
  303.     my $varref = shift;
  304.         if ($oldvarref)
  305.          {
  306.       $c->traceVdelete($oldvarref);
  307.          }
  308.     $c->{'-variable'} = $varref;
  309.     $c->traceVariable($varref, 'w', sub { $c->value($_[1]) });
  310.     $$varref = $oldval;
  311.     _layoutRequest($c,2);
  312.     }
  313.     $oldval;
  314. }
  315.  
  316. sub Destroyed
  317. {
  318.  my $c = shift;
  319.  my $var = delete $c->{'-variable'};
  320.  $c->traceVdelete($var);
  321. }
  322.  
  323. 1;
  324. __END__
  325.  
  326. =head1 NAME
  327.  
  328. Tk::ProgressBar - A graphical progress bar
  329.  
  330. =for category Derived Widgets
  331.  
  332. =head1 SYNOPSIS
  333.  
  334.     use Tk::ProgressBar;
  335.  
  336.     $progress = $parent->ProgressBar(
  337.     -width => 200,
  338.     -length => 20,
  339.         -anchor => 's',
  340.     -from => 0,
  341.     -to => 100,
  342.     -blocks => 10,
  343.     -colors => [0, 'green', 50, 'yellow' , 80, 'red'],
  344.     -variable => \$percent_done
  345.     );
  346.  
  347.     $progress->value($position);
  348.  
  349. =head1 DESCRIPTION
  350.  
  351. B<Tk::ProgressBar> provides a widget which will show a graphical representation
  352. of a value, given maximum and minimum reference values.
  353.  
  354. =head1 STANDARD OPTIONS
  355.  
  356. The following standard widget options are supported:
  357.  
  358. =over 4
  359.  
  360. =item B<-borderwidth>
  361.  
  362. =item B<-highlightthickness>
  363.  
  364. Defaults to 0.
  365.  
  366. =item B<-padx>
  367.  
  368. Defaults to 0.
  369.  
  370. =item B<-pady>
  371.  
  372. Defaults to 0.
  373.  
  374. =item B<-relief>
  375.  
  376. Defaults to C<sunken>
  377.  
  378. =item B<-troughcolor>
  379.  
  380. The color to be used for the background (trough) of the progress bar.
  381. Default is to use grey55.
  382.  
  383. =back
  384.  
  385. =head1 WIDGET-SPECIFIC OPTIONS
  386.  
  387. =over 4
  388.  
  389. =item B<-anchor>
  390.  
  391. This can be used to position the start point of the bar. Default
  392. is 'w' (horizontal bar starting from the left). A vertical bar can be
  393. configured by using either 's' or 'n'.
  394.  
  395. =item B<-blocks>
  396.  
  397. This controls the number of blocks to be used to construct the progress
  398. bar. The default is to break the bar into 10 blocks.
  399.  
  400. =item B<-colors>
  401.  
  402. Controls the colors to be used for different positions of the progress bar.
  403. The colors should be supplied as a reference to an array containing pairs
  404. of positions and colors.
  405.  
  406.   -colors => [ 0, 'green', 50, 'red' ]
  407.  
  408. means that for the range 0 to 50 the progress bar should be green
  409. and for higher values it should be red.
  410.  
  411.  
  412. =item B<-from>
  413.  
  414. This sets the lower limit of the progress bar.  If the bar is set to a
  415. value below the lower limt no bar will be displayed. Defaults to 0.
  416. See the C<-to> description for more information.
  417.  
  418. =item B<-gap>
  419.  
  420. This is the spacing (in pixels) between each block. Defaults to 1.
  421. Use 0 to get a continuous bar.
  422.  
  423.  
  424. =item B<-length>
  425.  
  426. Specifies the desired long dimension of the ProgressBar in screen
  427. units (i.e. any of the forms acceptable to Tk_GetPixels). For vertical
  428. ProgressBars this is the ProgressBars height; for horizontal scales it
  429. is the ProgressBars width.  The default length is calculated from the
  430. values of C<-padx>, C<-borderwidth>, C<-highlightthickness> and the
  431. difference between C<-from> and C<-to>.
  432.  
  433.  
  434. =item B<-resolution>
  435.  
  436. A real value specifying the resolution for the scale. If this value is greater
  437. than zero then the scale's value will always be rounded to an even multiple of
  438. this value, as will tick marks and the endpoints of the scale. If the value is
  439. less than zero then no rounding occurs. Defaults to 1 (i.e., the value will be
  440. integral).
  441.  
  442. =item B<-to>
  443.  
  444. This sets the upper limit of the progress bar. If a value is specified
  445. (for example, using the C<value> method) that lies above this value the
  446. full progress bar will be displayed. Defaults to 100.
  447.  
  448.  
  449.  
  450. =item B<-variable>
  451.  
  452. Specifies the reference to a scalar variable to link to the ProgressBar.
  453. Whenever the value of the variable changes, the ProgressBar will upate
  454. to reflect this value. (See also the B<value> method below.)
  455.  
  456. =item B<-value>
  457.  
  458. The can be used to set the current position of the progress bar
  459. when used in conjunction with the standard C<configure>. It is
  460. usually recommended to use the B<value> method instead.
  461.  
  462.  
  463. =item B<-width>
  464.  
  465. Specifies the desired narrow dimension of the ProgressBar in screen
  466. units (i.e.  any of the forms acceptable to Tk_GetPixels). For
  467. vertical ProgressBars this is the ProgressBars width; for horizontal
  468. bars this is the ProgressBars height.  The default width is derived
  469. from the values of C<-borderwidth> and C<-pady> and C<-highlightthickness>.
  470.  
  471. =back
  472.  
  473. =head1 WIDGET METHODS
  474.  
  475. =over 4
  476.  
  477. =item I<$ProgressBar>-E<gt>B<value>(?I<value>?)
  478.  
  479. If I<value> is omitted, returns the current value of the ProgressBar.  If
  480. I<value> is given, the value of the ProgressBar is set. If I<$value> is
  481. given but undefined the value of the option B<-from> is used.
  482.  
  483. =back
  484.  
  485.  
  486. =head1 AUTHOR
  487.  
  488. Graham Barr E<lt>F<gbarr@pobox.com>E<gt>
  489.  
  490. =head1 COPYRIGHT
  491.  
  492. Copyright (c) 1997-1998 Graham Barr. All rights reserved.
  493. This program is free software; you can redistribute it and/or modify it
  494. under the same terms as Perl itself.
  495.  
  496. =cut
  497.  
  498.  
  499.