| CGI-MxScreen documentation | view source | Contained in the CGI-MxScreen distribution. |
CGI::MxScreen::Screen - Ancestor for all user screens
use base qw(CGI::MxScreen::Screen);
sub display { # display screen -- defined
my $self = shift;
my ($arg1, $arg2) = @_;
...
}
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.
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.
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.
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 => colorOptinal. Overrides the default background for this screen.
-title => screen_titleMandatory. Sets the screen title.
The following attributes are defined:
bgcolorThe 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_screenThe 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.
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.
errorThe 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_envWhen 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.
managerThe CGI::MxScreen object who manages this screen.
nameThe screen name, as defined by the -screens argument when CGI::MxScreen
was built. See "Creation Routine" in CGI::MxScreen.
previous_screenThe 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_titleThis 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_screenThe 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.
varsThis 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.
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 via record_button().
set_error valueSet the error attribute, which is free for use by action callback, for
instance to propagate some error indication to the screen.
To make your screen a concrete class, you need to define the deferred
feature, display.
display argsThe 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().
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_screenCalled 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().
initCalled 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_screenCalled 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().
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, argsThis 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".
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 argsRecords 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.
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_errorThis 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().
The original authors are Raphael Manfredi <Raphael_Manfredi@pobox.com> and Christophe Dehaudt <Christophe.Dehaudt@teamlog.fr>.
Send bug reports, suggestions, problems or questions to Jason Purdy <Jason@Purdy.INFO>
CGI::MxScreen(3), CGI::MxScreen::Form::Button(3), CGI::MxScreen::Form::Field(3).
| CGI-MxScreen documentation | view source | Contained in the CGI-MxScreen distribution. |