Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

A Tk::Wizard Framework

by dhable (Monk)
on Jan 17, 2002 at 00:56 UTC ( #139336=sourcecode: print w/ replies, xml ) Need Help??

Category: GUI Programming
Author/Contact Info dhable
Description: This is my first attempt at writing a robust Perl library and I would like some honest feedback on how I could make this better. It's mainly a class that creates a GUI wizard control in Tk.

######################################################################
+#################
#
# Class:     Tk::Wizard
#
# Description:    The Tk::Wizard class is a Tk component that allows u
+sers to create a 
#               Microsoft style application wizard without having to w
+rite the code to 
#               manage the wizard framework components, like event dis
+patching, etc.
#
######################################################################
+#################



package Tk::Wizard;

use SelfLoader;
use Tk;
use Tk::JPEG;
use Tk::Text;
use strict;
no strict 'refs';


######################################################################
+################################
#
# Method:    new
#
# Description:    Creates a new object of type Tk::Wizard and sets the
+ default state
#
# Parameters:    None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub new($) {
    my $invocant = shift;
    my $class = ref( $invocant) || $invocant;
        my $self = { # required for GUI operation
             hWin             => $_[0],

             # configuration parameters
                     title             => "Generic Wizard",
                     filename             => "image.jpg",

                     # event handling references
                     preNextButtonAction    => undef,
                     postNextButtonAction    => undef,
                     
                     prePrevButtonAction     => undef,
                     postPrevButtonAction    => undef,
                     
                     preHelpButtonAction     => undef,
                     helpButtonAction        => undef,
                     postHelpButtonAction    => undef,
                     
                     preFinishButtonAction   => undef,
                     finishButtonAction      => undef,
                     postFinishButtonAction  => undef,
                      
                     preCancelButtonAction   => undef,
                     preCloseWindowAction    => undef,

                     # wizard page control list and ptr
                     wizardPageList          => [],    # ref to empty 
+array
                     wizardPagePtr           => 0,

             # internally used to track the wizard page being shown
             wizardFrame         => ""
                   };
    return bless( $self, $class);
} # end of sub new


######################################################################
+################################
#
# Method:    setActionEventHandlers
#
# Description:    Allows the documented set of actions to be overwritt
+en to hook the Tk::Wizard
#               framework into the application. While no handler must 
+be overwritten, it is
#               very useful to overwrite the helpButtionAction and the
+ finishButtonAction
#               event handlers.
#
# Parameters:    None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub setActionEventHandlers {
   my $self = shift;
   my %newHandlers = ( @_ );

   foreach( keys %newHandlers) {
      $self->{"$_"} = $newHandlers{$_};
   } # end of foreach
} # end of setActionEventHandlers


######################################################################
+################################
#
# Method:    setParamaters
#
# Description:    Provide useful definitions for the two main paramete
+rs - title and filename. title
#               refers to the scalar string that will be printed on th
+e wizard's title bar. filename
#               is the location and name of a JPEG file that should be
+ displayed on the left side of
#               the wizard.
#
# Parameters:    None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub setParameters {
   my $self = shift;
   my %newParams = ( @_ );

   foreach( keys %newParams) {
      $self->{"$_"} = $newParams{"$_"};
   } # end of foreach
} # end of setParameters


######################################################################
+################################
#
# Method:      addWizardPage
#
# Description: Puts the passed in wizard page at the end of the wizard
+ page list.
#
# Parameters:  $page    = The wizard page that should be added to the 
+end of the wizard list.
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub addWizardPage {
   my ($self, $page) = @_;
   push @{$self->{wizardPageList}}, $page;
} # end of sub addWizardPage


######################################################################
+################################
#
# Method:    currentPage
#
# Description:    Returns the page number that is currently being disp
+layed. Page counting starts with 1.
#
# Parameters:    None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub currentPage {
    my($self) = @_;
    return ($self->{wizardPagePtr} + 1);
} # end of sub currentPage
1;

######################################################################
+##############
# Functions below this level are only loaded on demand. This gives the
+ appearance of
# faster load times. See module SelfLoader for details.
######################################################################
+##############
__DATA__

sub parent {
    my ($self) = @_;
    return $self->{hWin};
}

######################################################################
+################################
#
# Method:    wpFrame
#
# Description:    This returns a Tk::Frame object that is a child of t
+he Wizard control. It should be
#         used when creating wizard pages since some padding parameter
+s are applied to it by
#         the wizard control.
#
# Parameters:    N/A
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub wpFrame {
    my ($self) = @_;

    my $frame = $self->{hWin}->Frame( -width => 400, -height => 400);
    $frame->packPropagate( 0);
    return $frame;
} # end of wpFrame


######################################################################
+################################
#
# Method:      Show
#
# Description: The Show method actually creates all of the necessary c
+omponents on the window that is
#              set in the new method. It is important that Wizard appl
+ications that use MainWindow for
#              drawing the Wizard also dispatch MainLoop after the Sho
+w method.
#
# Parameters:  None
#
# Exceptions:  N/A in this release
#
######################################################################
+################################
sub Show {
        my ($self) = @_;

    #
    # builds the buttons on the bottom of thw wizard
    #
    my $buttonPanel = $self->{hWin}->Frame();
    $buttonPanel->Button( -text => "Cancel", 
                              -command => [ \&CancelButtonEventCycle, 
+$self, $self->{hWin}], 
                              -width => 10
                            ) ->pack( -side => "right", -expand => 0);

    $self->{nextButtonRef} = $buttonPanel->Button( -text => "Next >", 
                           -command => [ \&NextButtonEventCycle, $self
+ ],
                           -width => 10
                                             )->pack( -side => "right"
+, -expand => 0);

    $self->{prevButtonRef} = $buttonPanel->Button( -text => "< Previou
+s", 
                                               -command => [ \&PrevBut
+tonEventCycle, $self ], 
                           -width => 10,
                           -state => "disabled"
                         )->pack( -side => "right", -expand => 0);

    $buttonPanel->Button( -text => "Help", 
                              -command => [ \&HelpButtonEventCycle, $s
+elf ], 
                              -width => 10
                            )->pack( -side => 'left', -anchor => 'w');

    $buttonPanel->pack( -side => "bottom", -fill => 'x', -pady => 4, -
+padx => 4);


    #
    # builds the image on the left side of the wizard
    #
    $self->{hWin}->Photo( "sidebanner", -format => "jpeg", -file => $s
+elf->{filename});
    $self->{hWin}->Label( -image => "sidebanner")->pack( -side => "lef
+t", -anchor => "w");


    #
    # This populates the wizard page panel on the side of the screen.
    #
        $self->{wizardFrame} = 
            $self->{wizardPageList}->[($self->{wizardPagePtr})]->()->p
+ack( -side => "top", -expand => 0);


    #
    # setup the containing window to match the criteria for a wizard w
+idget
    #
    $self->{hWin}->configure( -title => $self->{title});
    $self->{hWin}->resizable( 0, 0);        # forbid resize
    $self->{hWin}->withdraw;                # position in screen cente
+r
    $self->{hWin}->Popup;
    $self->{hWin}->transient;               # forbid minimize
        $self->{hWin}->protocol( WM_DELETE_WINDOW => [ \&CloseWindowEv
+entCycle, $self, $self->{hWin}]);
} # end of sub Show


######################################################################
+################################
#
# Method:       dispatch
#
# Description:  Thin wrapper to dispatch event cycles as needed
#
# Parameters:    The dispatch function is an internal function used to
+ determine if the dispatch back reference
#         is undefined or if it should be dispatched. Undefined method
+s are used to denote dispatchback
#         methods to bypass. This reduces the number of method dispatc
+hs made for each handler and also
#         increased the usability of the set methods above when trying
+ to unregister event handlers.
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub dispatch {
    my ($handler) = @_;
    if( defined $handler) { return !($handler->());}
    return 0;
} # end of sub dispatch


######################################################################
+################################
#
# Method:      NextButtonEventCycle
#
# Description: Runs the complete view of the action handler cycle for 
+the "Next>" button on the
#              wizard button bar. This includes dispatching the preNex
+tButtonAction and
#              postNextButtonAction handler at the apporprate times.
#
# Parameters:    None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub NextButtonEventCycle {
   my ($self) = @_;
   if( dispatch( $self->{preNextButtonAction})) { return;}

   # advance the wizard page pointer and then adjust the navigation bu
+ttons.
   # readraw the frame when finished to get changes to take effect.
   $self->{wizardPagePtr}++;
   $self->{wizardPagePtr} = $#{$self->{wizardPageList}} if( $self->{wi
+zardPagePtr} >= $#{ $self->{wizardPageList}});

   if( $self->{nextButtonRef}->cget( -text) eq "Finish") {
      if( dispatch( $self->{finishButtonAction})) { return; }
      $self->CloseWindowEventCycle();
   }
   $self->{prevButtonRef}->configure( -state => "normal");
   $self->{nextButtonRef}->configure( -text => "Finish") if( $self->{w
+izardPagePtr} == $#{ $self->{wizardPageList}});
   $self->redrawWizardPage;

   if( dispatch( $self->{postNextButtonAction})) { return; }
} # end of sub NextButtonEventCycle


######################################################################
+################################
#
# Method:      PrevButtonEventCycle
#
# Description: Runs the complete view of the action handler cycle for 
+the "<Previous" button on the
#              wizard button bar. This includes dispatching the prePre
+vButtonAction and
#              postPrevButtonAction handler at the apporprate times.
#
# Parameters:    None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub PrevButtonEventCycle {
   my ($self) = @_;
   if( dispatch( $self->{prePrevButtonAction})) { return; }


   # move the wizard pointer back one position and then adjust the nav
+igation buttons
   # to reflect any state changes. Don't fall off end of page pointer
   $self->{wizardPagePtr}--;
   $self->{wizardPagePtr} = 0 if( $self->{wizardPagePtr} < 0);
   
   $self->{nextButtonRef}->configure( -text => "Next >");
   $self->{prevButtonRef}->configure( -state => "disabled") if( $self-
+>{wizardPagePtr} == 0);
   $self->redrawWizardPage;

   if( dispatch( $self->{postPrevButtonAction})) { return; }
} # end of sub PrevButtonEventCycle


######################################################################
+################################
#
# Method:      HelpButtonEventCycle
#
# Description: This generates all of the events required when the Help
+ button is clicked. This runs
#              through the pre event handler, the event handler and th
+en the post event handler. If
#              no event handlers are defined, the method does nothing.
#
# Parameters:    None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub HelpButtonEventCycle {
   my ($self) = @_;
   if( dispatch( $self->{preHelpButtonAction})) { return; }
   if( dispatch( $self->{helpButtonAction})) { return; }
   if( dispatch( $self->{postHelpButtonAction})) { return; }
} # end of sub HelpButtonEventCycle


######################################################################
+################################
#
# Method:      CancelButtonEventCycle
#
# Description: This generates all of the necessary events reqruied for
+ a good Wizard control when
#              the cancel button is clicked. This involves dispatching
+ the preCancelButtonAction handler
#              and then activating the CloseWindowEventCycle to run th
+rough the process of closing
#              the window.
#
# Parameters:    None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub CancelButtonEventCycle {
   my ($self, $hGUI) = @_;
   if( dispatch( $self->{preCancelButtonAction})) { return;}
   $self->CloseWindowEventCycle( $hGUI);
} # end of sub CancelButtonEventCycle


######################################################################
+################################
#
# Method:      CloseWindowEventCycle
#
# Description: This generates all of the necessary events required for
+ a good Wizard control when
#              the Window is about to be closed. This involves dispatc
+hing the preCloseWindowAction handler
#              and then destroying the reference to the Window control
+.
#
# Parameters:    None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub CloseWindowEventCycle {
   my ($self, $hGUI) = @_;
   if( dispatch( $self->{preCloseWindowAction})) { return;}
   $hGUI->destroy;
} # end of sub CloseWindowEventCycle


######################################################################
+################################
#
# Method:      redrawWizardPage
#
# Description: Update the wizard page panel by unpacking the existing 
+controls and then repacking.
#              This allows updates to the page pointer to become visib
+le.
#
# Parameters:  None
#
# Exceptions:    N/A in this release
#
######################################################################
+################################
sub redrawWizardPage {
   my ( $self) = @_;

   $self->{wizardFrame}->packForget;
   $self->{wizardFrame} = $self->{wizardPageList}->[$self->{wizardPage
+Ptr}]->()->pack( -side => "top");
} # end of sub redrawWizardPagePanel


#############################
# End of Package Tk::Wizard #
#############################
1;
__END__
=head1 NAME

Tk::Wizard - GUI Wizard Framework

=head1 SYNOPSIS


   use Tk::Wizard;
  
   my $wizard = new Wizard( new MainWindow);
   $wizard->addWizardPage( \&createPage1);
   $wizard->addWizardPage( \&createPage2);
   $wizard->addWizardPage( \&createPage3);
   $wizard->Show();
   
   MainLoop;

=head1 DESCRIPTION

The Tk::Wizard class automates a large part of creating a program wiza
+rd to collect information and then
perform some complex task based upon the answers and information gathe
+red from the user. The wizard feel
is largly based upon the Microsoft wizard style that appeared in produ
+cts like Office 95 and Office 97.

=head1 METHODS

=head2 Tk::Wizard-E<gt>new( @args)

Creates a new instance of the Tk::Wizard object. The @args list is a h
+ash list of the different
options that can be specified for the class. These include:

Parameters:

   -title => This is the title that will be displayed in the Windows t
+itle bar
   
   -filename => This is the path and name of a JPEG file that will be 
+displayed on the right side
                of the screen.

Action Event Handlers:
                
   -preNextButtonAction => This is a reference to a function that will
+ be dispatched before the Next
                           button is processed.
                           
   -postNextButtonAction => This is a reference to a function that wil
+l be dispatched after the Next
                            button is processed.
                            
   -prePrevButtonAction => This is a reference to a function that will
+ be dispatched before the Previous
                           button is processed.
                           
   -postPrevButtonAction => This is a reference to a function that wil
+l be dispatched after the Previous
                            button is processed.
                            
   -preHelpButtonAction => This is a reference to a function that will
+ be dispatched before the Help
                           button is processed.
                           
   -helpButtonAction => This is a reference to a function that will be
+ dispatched to handle the Help
                        button action.
                            
   -postHelpButtonAction => This is a reference to a function that wil
+l be dispatched after the Help
                            button is processed.

   -preFinishButtonAction => This is a reference to a function that wi
+ll be dispatched before the Finish
                             button is processed.
                             
   -finishButtonAction => This is a reference to a funciton that will 
+be dispatched to handle the Finish
                          button action.
                          
   -postFinishButtonAction => This is a reference to a function that w
+ill be dispatched after the Finish
                              button is processed.
                              
   -preCancelButtonAction => This is a reference to a function that wi
+ll be dispatched before the Cancel
                             button is processed.
                             
   -preCloseWindowAction => This is a reference to a funciton that wil
+l be dispatched before the window
                            is issued a close command.

    See the section Action Event Handlers for more details.
                                               
=head2 Tk::Wizard-E<gt>setActionEventHandlers( @args)

This method can be used to set or change the action event handler func
+tions of a Tk::Wizard instance.
The @args list accepts any Action Event Handler value pairs that could
+ be passed into the new method.

See the section Action Event Handlers for more details.

=head2 Tk::Wizard-E<gt>setParameters( @args)

This method can be used to set or change the parameters of a Tk::Wizar
+d instance. The @args list
accepts any Parameter value pairs that could be passed into the new me
+thod.

=head2 Tk::Wizard-E<gt>Show()

This method must be dispatched before the Wizard will be displayed. 

=head2 Tk::Wizard-E<gt>addWizardPage( $page)

This method is used to add a Wizard page to the wizard. The $page para
+meter must be a Tk::Frame object.
The pages are stored and will be displayed in the order that they were
+ added to the Wizard control.

=head2 Tk::Wizard-E<gt>currentPage()

This returns the index of the page that is currently shown. Pages are 
+indexed starting at 0 with the
first page that is associated with the wizard through the addWizardPag
+e method.

=head2 Tk::Wizard-E<gt>wpFrame()

This returns a wizard page frame. This method should be called when th
+e user of the wizard wants to
build the page specific controls.

=head2 Tk::Wizard-E<gt>parent

This returns the parent Tk widget that was used to create the wizard a
+nd all of the controls. This is
defined as part of the new method.

=head1 Action Event Handlers

The action event handler functions should not accept and parameters an
+d return a TRUE or FALSE variable. If
the remainder of the action should continue a TRUE value is returned. 
+If a FALSE value is returned, execution
of the event handler stops. This can be used to prompt the user if the
+y want to quit and take action based upon
the input.

=head1 SUPPORT

A list of the current development efforts can be found at 
http://www.uwm.edu/~dthable/perl

=head1 COPYRIGHT

Copyright (c) 2002 Daniel T. Hable

Permission is hereby granted, free of charge, to any person obtaining 
+a copy of this software and associated 
documentation files (the "Software"), to deal in the Software without 
+restriction, including without limitation 
the rights to use, copy, modify, merge, publish, distribute, sublicens
+e, and/or sell copies of the Software, 
and to permit persons to whom the Software is furnished to do so, subj
+ect to the following conditions:

The above copyright notice and this permission notice shall be include
+d in all copies or substantial portions of 
the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRES
+S OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ AND NONINFRINGEMENT. IN NO EVENT SHALL 
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR O
+THER LIABILITY, WHETHER IN AN ACTION OF 
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WIT
+H THE SOFTWARE OR THE USE OR OTHER 
DEALINGS IN THE SOFTWARE.

=cut

Comment on A Tk::Wizard Framework
Download Code
Re: A Tk::Wizard Framework
by Anonymous Monk on Nov 14, 2002 at 12:26 UTC
    Have you seen http://www1.clearlight.com/~oakley/tcl/tkwizard/index.html ?
      How do you run the program? I've downloaded both the .zip and the .tar
Re: A Tk::Wizard Framework
by Anonymous Monk on Jun 07, 2013 at 00:21 UTC
    For anyone interested, there is now a Tk::Wizard based/inspired by this on CPAN :)

Back to Code Catacombs

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: sourcecode [id://139336]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (16)
As of 2015-07-02 19:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (45 votes), past polls