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 toprevious_screen
andspring_screen
. -
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 byCGI::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 whenCGI::MxScreen
was built. See "Creation Routine" in CGI::MxScreen. previous_screen
-
The previously displayed screen, in the same form as
current_screen
. It will beundef
the first time.If you had a transition from one screen to the same one, then
previous_screen
andcurrent_screen
will return the same information. However, seespring_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 theCGI
module, andCGI
exports atitle()
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:
-
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 viarecord_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. thebounce()
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, becauseCGI::MxScreen
is supposed to handle that for you, and also the onlydisplay()
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()
andrecord_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 thedisplay()
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".
-
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).