The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

CGI::MxScreen::Screen - Ancestor for all user screens

SYNOPSIS

 use base qw(CGI::MxScreen::Screen);

 sub display {                # display screen -- defined
     my $self = shift;
     my ($arg1, $arg2) = @_;
     ...
 }

DESCRIPTION

This deferred class is meant to be the ancestor of all your application screens. You must inherit from CGI::MxScreen::Screen and at least define the display() routine, which will be called by the CGI::MxScreen manager when that screen is selected for display.

CGI::MxScreen::Screen objects are blessed hashes. In order to leave you as much of the key namespace as possible, all attributes defined by the deferred class start with two leading underscores. Contrary to the routine namespace (see "INTERFACE" below), this simple workaround should prevent any accidental attribute collision.

Screen objects must be serializable. That means they must never hold or refer to objects or data containing things known to be non-serializable, like GLOB and CODE references.

Screen objects are never created by the user. They are handled by the CGI::MxScreen manager, who will ensure that at most one instance of each screen name will be created during a session. That means the init() routine will be called at most once. I say at most because screens are created on demand, and if your application does not need to show some state during a session, then the screen object will never be created.

INTERFACE

Because you need to inherit, you must be very familiar with the internals of the class, i.e. not just only the public interface, but also with the routines used throughout the framework but not meant for public consumption. Indeed, Perl will not warn you when you accidentally define a routine bearing the same name as one present in the ancestors (i.e. redefinition is automatic, which is dangerous here). And redefining routines as essential as validate() or name() would lead to havoc.

Listing

Before detailing the interface, here is a compact list of all the public features, to make it easier to see what is provided (and know which routine names are forbidden to you... A trailing + indicates a routine that you may choose to redefine, a trailing * indicates a deferred routine, which you must define. Functions listed between (parenthesis) are action callbacks, not meant to be called directly.

The following interface is public, i.e. you may safely use those features on screen objects:

    (abort_on_error)
    bgcolor
    bounce
    (clear_context)
    current_screen
    default_button
    display*
    enter+
    error
    error_env
    init+
    leave+
    manager
    name
    previous_screen
    record_button
    record_field
    screen_title
    set_default_button
    set_error
    spring_screen
    (validate)
    vars

The following interface is private, i.e. you should never make direct use of those features on screen objects. It is used internally by CGI::MxScreen and is documented (well, listed) so that you never define a feature bearing that name in your own classes.

Those names you should absolutely never override:

    make
    remake
    relink_to_manager
    _init
    set_error_env
    _clear_internal_context

You must also know that, in order to be serializable with Storable, the screen defines the following hooks:

    STORABLE_freeze
    STORABLE_thaw

If for some reason you need to redefine those hooks, you can't simply call SUPER:: on them, whilst doing your local processing in the redefinition. Look at the source code to understand what needs to be done.

Because the above hooks were necessary, it means that adding other serializer support (see CGI::MxScreen::Serializer) will probably require similar hooks. Unfortunately, although we could design things so as to make this choice possible, the only serializer we knew about was Storable.

Creation Routine

Screens are created automatically by the CGI::MxScreen manager, based on the -screens settings, as explained in "Creation Routine" in CGI::MxScreen. The only special argument is -class, which is handled internally by CGI::MxScreen, but the others are passed verbatim to the screen creation routine.

The supported arguments are:

-bgcolor => color

Optinal. Overrides the default background for this screen.

-title => screen_title

Mandatory. Sets the screen title.

Attributes

The following attributes are defined:

bgcolor

The background color (string form, i.e. either a color name like "gray" or an hexadecimal representation of the RGB triplet like "#1e32ef") used to display this screen.

current_screen

The current screen being displayed, along with the display() arguments, as an array reference, for instance:

    ["Welcome", 010125]

where the first item is the screen name, the remaining are the displaying arguments. This makes it possible to use that as a -target argument for buttons (see CGI::MxScreen::Form::Button).

Note: The notion of current_screen is maintained by the manager. Whatever screen object you query, you will always obtain the same answer. This note also applies to previous_screen and spring_screen.

default_button

The default button recorded via set_default_button.

The default button is used when the user presses <Enter> when submitting a form, without pressing one of the submit buttons. Usually, browsers allow this when there is only one CGI input field in the form.

If there is no default button specified, CGI::MxScreen will remain in the current state and redisplay the screen.

error

The error information, recorded vi set_error. This is a user-defined field, i.e. it is not used by CGI::MxScreen. It is meant to be filled by action callbacks, when an error is detected. Since it will be used by your own screens, you may put whatever you wish.

error_env

When an action callback failed, this attribute holds the CGI::MxScreen::Action_Env object used during the execution of the callback chain. See CGI::MxScreen::Action_Env for its access interface.

The attribute is otherwise undef, so you may test it boolean-wise to determine whether an error did occur or not.

manager

The CGI::MxScreen object who manages this screen.

name

The screen name, as defined by the -screens argument when CGI::MxScreen was built. See "Creation Routine" in CGI::MxScreen.

previous_screen

The previously displayed screen, in the same form as current_screen. It will be undef the first time.

If you had a transition from one screen to the same one, then previous_screen and current_screen will return the same information. However, see spring_screen.

screen_title

This is the title of the screen, as configured during the creation of the CGI::MxScreen manager, via the -screens argument. See "Creation Routine" in CGI::MxScreen.

It is not called simply title because screens may use the CGI module, and CGI exports a title() routine as part of its HTML generation routines.

spring_screen

The screen we sprang from. This is the last stable state we were in before jumping into the current screen, transitions to the same screen not withstanding. The format is the same as current_screen.

This may be used as -target for buttons to come back to the screen that directed a transition to the current screen, whatever it was. See CGI::MxScreen::Form::Button.

vars

This returns a reference to a global persistent hash table, available in all states. It is free for use by user screens, but all the values you will store there must be serializable (by Storable, or any other serializer you configured).

By default, access to keys within this hash table are protected, to guard against typos (at runtime, alas). If you don't like that behaviour, you can set $mx_check_vars to false in the global configuration. See CGI::MxScreen::Config.

Attribute Setting

The following routines allow changing of some attributes:

set_default_button button_object

Records a default button for the screen, to be used if they press <Enter> to submit the form data. The button_object is a CGI::MxScreen::Form::Button object, obtained via record_button().

set_error value

Set the error attribute, which is free for use by action callback, for instance to propagate some error indication to the screen.

Feature To Be Defined

To make your screen a concrete class, you need to define the deferred feature, display.

display args

The routine that displays the CGI form.

It is called by the CGI::MxScreen manager, with some arguments, as defined by the -initial argument (see "Creation Routine" in CGI::MxScreen) or by the -target button argument (see CGI::MxScreen::Form::Button), or generally speaking, anything that defines a state transition (e.g. the bounce() routine, as described below).

Before calling the routine, CGI::MxScreen initialized the HTML headers and opened the form tag, directing the submission to the script's URL, but without the query string: if one is supplied initially, it is up to you to save the relevant information in the persistent context, or in your screen objects, since they are also persistent.

The routine must print to STDOUT its generated HTML, and can make use of all the helper routines from the CGI module to generate form controls or emit HTML via routines. There are also some other helper routines defined in CGI::MxScreen::HTML.

When it returns, the screen is supposed to have been fully displayed, and the form will be closed automatically by CGI::MxScreen. If you haven't read them already, you should study "Example" in CGI::MxScreen and CGI::MxScreen::Layout.

A screen is given the opportunity to redirect itself to another state, by sending a bounce execption to the manager via bounce(). However, it may do so only if it has not already emitted anything. If you left $mx_buffer_stdout to its default true setting (see CGI::MxScreen::Config), anything you output before bouncing will be discarded for you.

Usually, your screens will define fields and submit buttons. You should record them to be able to attach validation routines or action callbacks, but you may choose not to and use plain raw CGI routines, with manual hidden context propagation. However, note that it would be a waste, because CGI::MxScreen is supposed to handle that for you, and also the only display() routine called is the one for the visible screen. Any other parameters defined on other screens would not even have the opportunity to hide themselves... As for buttons, not recording them means you won't be able to make use of the state machine features.

To record fields and buttons, use record_field() and record_button().

Features To Be Redefined

The following features have empty default implementations, and are meant to be redefined in your screens. It is not necessary to redefine all of them, or any of them, if you don't need them:

enter from_screen

Called when we enter a screen whilst coming from another one. The screen object we sprang from is given as argument, but will be undef for the very first screen displayed (the initial screen).

Note: we're passed a screen object, not a list representation like the one returned by spring_screen().

init

Called when the screen object is created.

You may do whatever initialization is necessary on your object, but remember that screen objects are created once and remain persistent accross the whole session. Therefore, if you need runtime initialization each time one enters this screen, write it within enter().

leave to_screen

Called when we leave a screen to go to to_screen, which is a screen object. Contrary to enter(), this one is always defined, by construction.

Note: we're passed a screen object, not a list representation like the one returned by spring_screen().

Control Features

Those features are necessary to let the screen control what's going to happen when the form is submitted. They are meant to be used during display() processing:

bounce screen_name, args

This is an exception (sic!) to the definition given above. By calling bounce(), a screen redirects the state machine to the screen called screen_name, with args being the display() arguments.

You should not call bounce() after having emitted something. This feature is meant to be an exception, allowing to bypass a state when some condition is met.

To avoid endless loops, there is an hardwired limit of 20 consecutive bounces allowed. As famous people said on other occasion when talking about computer limits, "this should be sufficient for any application".

record_button args

Records a submit button, and returns a CGI::MxScreen::Form::Button object. Please see CGI::MxScreen::Form::Button for the interface, and the description of what args can be.

record_field args

Records a control field, and returns a CGI::MxScreen::Form::Field object. Please see CGI::MxScreen::Form::Field for the interface, and the description of what args can be.

Action Callbacks

Those features are not meant to be used directly, but are provided so that they can be used as action callbacks attached to buttons, as described in CGI::MxScreen::Form::Button.

The most important one is 'validate' (spelled as a string because this is how it should be used: see "Callbacks" in CGI::MxScreen), which will trigger all the field verfication and patching callbacks.

abort_on_error

This callback returns CGI_MX_ABORT to immediately abort the callback chain if there is an error already in one of the preceding callbacks. See CGI::MxScreen::Error.

clear_context [screen_name]

Clears a specific section of the overal context where orphan CGI parameters are saved. A CGI parameter is orphan if there was no record_field() done for it.

If screen_name is not specified, this applies to the current screen.

This callback is useful if you wish to discard the state of orphan CGI parameters, so that the next time they are created, they get their default value.

validate [continue]

Runs the validation and patching callbacks on all the recorded fields for this screen. If continue is true, any error will not be fatal immediately, i.e. CGI_MX_ERROR will be returned, so that other action callbacks may execute. If not specified, it defaults to false, meaning a failed validation immediately triggers the error and the end of the action callback sequence.

Here is an example of action callback settings for a submit button:

    my $ok = $self->record_button(
        -name       => "OK",
        -target     => "Next",
        -action     => [
            'validate',                 # Same as ['validate', 0]
            ['do_something', $self],
            'abort_on_error',
            ['clear_context', "Next"],
        ]
    );

See CGI::MxScreen::Form::Button for more information on record_button().

AUTHORS

Raphael Manfredi <Raphael_Manfredi@pobox.com> and Christophe Dehaudt <Christophe.Dehaudt@teamlog.fr>.

SEE ALSO

CGI::MxScreen(3), CGI::MxScreen::Form::Button(3), CGI::MxScreen::Form::Field(3).