package require StateManager
set state StateManager %AUTO% ?options?
$state method ?parameters?
set singleton [StateManagerSinleton %AUTO% ?options?]
While packaged with the ReadoutGUI this is actually a general purpose utility that provides support for Tcl script to save and restore state variables. A state variable can be pretty much anything that might define the state of a program or control how a program operates.
State is saved to and restored from Tcl scripts that consist entirely of set commands. These scripts are sourced into a safe interpreter in order to ensure they cannot damage or inject insecure code into the application itself.
Only pre-declared state variables will be saved or restored from the file, further securing the application script from malicious or erroneous restores.
Note that if an application has several independent components
that wish to share a single configuration file, the
StateManagerSingleton
can be used to provide
access to an application speciric singleton state manager object.
StateManager
objects include the
standard configure
and
cget
methods. These operate on
the object option(s) described below.
-file
file-path
Provides the path to the file that will be used by
save
and
restore
operations.
See METHODS below.
In addtion to the configure
and
cget
methods described in
OPTIONS above, the following methods are provided by
StateManager
objects
destroy
Destroys the object.
addStateVariable
name getter setter
Defines a state variable that will be saved/restored
by the state manager. name
is
the name of the variable as it will be defined in
the file (e.g. set name value).
getter
is a command to which name
will be appended that will be used by save
to obtain the variable value.
setter
is a command which will be called by
restore
to restore the value of name.
name
and value
will be appended to
the setter command.
If this business of getters and setters is not clear
see save
and
restor
and finally
the EXAMPLES section below.
listStateVariables
Returns a list of the state variables. The return value is a Tcl list of triplets. Each triplet conisists of a variable name, its getter and setter in that order.
save
Saves the variables to -file
.
If the -file
option is blank an
error is thrown.
The save operates by iterating over all registered variables and writing a command that is something like
to the file.
Creates a secure slave interpreter and sources
-file
into that interpreter.
For each variable in the list of state variables,
if the slave interpreter has a definition for that
variable, the setter for that variable is called in
code something like this:
The example below shows how to define two state variables
::State::var1
and ::State::var2
and their associated getter/setter procs.
Example 1. Getters and setters for StateManager
namespace eval ::State { variable var1 variable var2 } ... proc ::State::getter name { return [set ::State::$name] } proc ::State::setter {name value} { set ::State::$name $value } set sm [StateManagerSingleton %AUTO%] $sm addStateVariable var1 ::State::getter ::State::setter $sm addStateVariable var2 ::State::getter ::State::setter ... $sm configure -file /path/to/configuration/file.tcl $sm save ... $sm restore
var1
and
var2
which will be saved and restored.
var1
and var2
are registered with getters and setters defined
as described above so that each variable is bound to
the corresponding variable in the ::State
namespace.
It's worth nothing that more interesting setter and getter functions are possible. For example, a setter could load a piece of a graphical user interface, and a getter could retrieva a value from an element of a graphical user interface. The ReadoutShell does this in a few places.
-file
must be configured to point at a file (or specify a writable file
for save) that is used as the target for the save or source for
the restore. -file
can be freely configured
many times. For example your application might prompt the user
for a filename into which some configuration information
can be written/read.
::State::var1
and ::State::var2
to the last configured
-file
. This is done by invoking the
getter registered for each of those variables (and any other
variables that were added for that matter) in turn passing in
var1 and var2 to
retrieve their values.
-file
into a slave safe interpreter and queries that interpreter
to see if each registered variable is defined. For each
defined variable, the value is fetched out of the interpreter
and that variable's setter is invoked to update whatever
in the application is bound to that configuration variable.