package Tk::Wizard::Choices; use strict; use warnings; use warnings::register; use vars '$VERSION'; $VERSION = do { my @r = ( q$Revision: 2.76 $ =~ /\d+/g ); sprintf "%d." . "%03d" x $#r, @r }; use Carp (); # use Scalar::Util qw( reftype ); =head1 NAME Tk::Wizard::Choices - C pages to collect end-user choices =head1 SYNOPSIS Currently automatically loaded by C, though this behaviour is deprecated and is expected to change in 2008. =head1 DESCRIPTION Adds a number of methods to C, to collect choices made by the end-user. =head1 METHODS =head2 addMultipleChoicePage Allow the user to make multiple choices among several options: each choice sets a variable passed as reference to this method. Accepts the usual parameters plus: =over 4 =item -relief For the checkbox buttons - see L. =item -choices A reference to an array of hashes with the following fields: =over 4 =item -title Title of the option, will be rendered in bold =item -subtitle Text rendered smaller beneath the title =item -variable Reference to a variable that will contain the result of the choice. Croaks if none supplied. Your -variable will contain the default L values of 1 for checked and 0 for unchecked. =item -checked Pass a true value to specify that the box should initially appear checked. =back Here is an example of what the -choices parameter should look like: $wizard->addMultipleChoicePage( -title => "Another toy example", -choices => [ { -title => 'choice 1', -variable => \$choice1, }, { -title => 'choice 2, default is checked', -variable => \$choice2, -checked => 1, }, ], ); =back =cut sub Tk::Wizard::addMultipleChoicePage { my $self = shift; my $args = {@_}; return $self->addPage( sub { $self->_page_multiple_choice($args) } ); } sub Tk::Wizard::_page_multiple_choice { my $self = shift; my $args = shift; my $frame = $self->blank_frame(%$args); if ( !ref( $args->{-choices} ) || ( ref( $args->{-choices} ) ne 'ARRAY' ) ) { Carp::croak "-choices should be a ref to an array!"; } my $content = $frame->Frame( -background => $self->{background}, )->pack( -side => 'top', -anchor => "n", -padx => 10, -pady => 10, ); foreach my $opt ( @{ $args->{-choices} } ) { Carp::croak "Option in -choices array is not a hash!" if not ref $opt or ref $opt ne 'HASH'; Carp::croak "No -variable!" if not $opt->{-variable}; Carp::croak "-variable should be a reference!" if not ref $opt->{-variable}; my $b = $content->Checkbutton( -text => $opt->{-title}, -justify => 'left', -relief => $args->{-relief} || 'flat', -font => "RADIO_BOLD", -variable => $opt->{-variable}, -background => $self->{background}, -activebackground => $self->{background}, )->pack(qw/-side top -anchor w /); $b->invoke if $opt->{-checked}; my $s = $opt->{-subtitle} || ''; # Seven spaces indentation is perfect with my Windows XP # default font: $s =~ s!(^|\n)!$1 !g; my $l = $content->Label( -font => $self->{defaultFont}, -text => $s, -anchor => 'w', -justify => 'left', -background => $self->{background}, )->pack(qw/-side top -anchor w/); # DEBUG_FRAME && $l->configure( -background => 'light blue' ); } return $frame; } =head2 addSingleChoicePage Allow the user to make one choice from among several options (i.e. a group of radio buttons). Each choice sets a variable passed as reference to this method. Accepts the usual parameters plus: =over 4 =item -relief For the radio buttons - see L. =item -variable Reference to a variable that will contain the result of the choice. Croaks if none supplied. Your -variable will contain the -value of the radio button that is selected when the user clicks "Next". =item -choices A reference to an array of hashes with the following fields: =over 4 =item -title Title of the option, will be rendered in bold =item -subtitle Text rendered smaller beneath the title =item -value This value will be placed in your -variable variable if this button is selected =item -selected Pass a true value to specify that this radio should initially appear selected. If none of the choices have -selected, then the first choice will be selected by default. =back Here is an example of what the -choices parameter should look like: $wizard->addSingleChoicePage( -title => 'Another toy example', -text => 'Choose one of the following:', -variable => \$choice, -choices => [ { -title => 'choice 1', -value => 1, }, { -title => 'choice two, default this one selected', -value => 'two', -selected => 1, }, ], ); =back =cut sub Tk::Wizard::addSingleChoicePage { my $self = shift; # We have to make a copy of our args in order for them to get # "saved" in this coderef: my $args = {@_}; # print STDERR " DDD addSingleChoicePage args are ", Dumper($args); return $self->addPage( sub { $self->_page_single_choice($args) } ); } sub Tk::Wizard::_page_single_choice { my $self = shift; my $args = shift; my $not_first_page = 0; if (not defined( $args->{-choices} ) ) { Carp::croak "-choices argument missing"; } if (not ref( $args->{-choices} ) or ( ref( $args->{-choices} ) ne 'ARRAY' ) ) { Carp::croak "-choices must be a ref to an array!"; } Carp::croak "-variable argument missing" if !defined( $args->{-variable} ); Carp::croak "-variable must be a reference!" if !ref $args->{-variable}; # Take care of the -title, -text, etc.: my $frame = $self->blank_frame(%$args); my $content = $frame->Frame( -background => $self->{background}, )->pack( -side => 'top', -anchor => "n", -padx => 10, -pady => 10, ); foreach my $opt ( @{ $args->{-choices} } ) { # if ( reftype($opt) ne 'HASH' ) { if ( ref $opt ne 'HASH' ) { Carp::croak "Option in -choices array must be a hash"; } $opt->{-title} ||= ''; my $sValue = $opt->{-value} || $opt->{-title}; my $b = $content->Radiobutton( -text => $opt->{-title}, -justify => 'left', -relief => $args->{-relief} || 'flat', -font => "RADIO_BOLD", -variable => $args->{-variable}, -value => $sValue, -background => $self->{background}, -activebackground => $self->{background}, )->pack(qw/-side top -anchor w /); ${ $args->{-variable} } = $sValue if not $not_first_page++; ${ $args->{-variable} } = $sValue if $opt->{-selected}; my $s = $opt->{-subtitle} || ''; # Seven spaces indentation is perfect with my Windows XP default font: if ( $s ne '' ) { $s =~ s!(^|\n)!$1 !g; my $l = $content->Label( -font => $self->{defaultFont}, -text => $s, -anchor => 'w', -justify => 'left', -background => $self->{background}, )->pack(qw/-side top -anchor w/); # DEBUG_FRAME && $l->configure( -background => 'light blue' ); } } return $frame; } 1; =head1 AUTHOR Lee Goddard (lgoddard@cpan.org). =head1 COPYRIGHT Copyright (C) Lee Goddard, 11/2002 - 01/2008 ff. Made available under the same terms as Perl itself.