Provided by: tcllib_1.19-dfsg-2_all bug

NAME

       snit - Snit's Not Incr Tcl

SYNOPSIS

       package require Tcl  8.5

       package require snit  ?2.3.2?

       snit::type name definition

       typevariable name ?-array? ?value?

       typemethod name arglist body

       typeconstructor body

       variable name ?-array? ?value?

       method name arglist body

       option namespec ?defaultValue?

       option namespec ?options...?

       constructor arglist body

       destructor body

       proc name args body

       delegate method name to comp ?as target?

       delegate method name ?to comp? using pattern

       delegate method * ?to comp? ?using pattern? ?except exceptions?

       delegate option namespec to comp

       delegate option namespec to comp as target

       delegate option * to comp

       delegate option * to comp except exceptions

       component comp ?-public method? ?-inherit flag?

       delegate typemethod name to comp ?as target?

       delegate typemethod name ?to comp? using pattern

       delegate typemethod * ?to comp? ?using pattern? ?except exceptions?

       typecomponent comp ?-public typemethod? ?-inherit flag?

       pragma ?options...?

       expose comp

       expose comp as method

       onconfigure name arglist body

       oncget name body

       snit::widget name definition

       widgetclass name

       hulltype type

       snit::widgetadaptor name definition

       snit::typemethod type name arglist body

       snit::method type name arglist body

       snit::macro name arglist body

       snit::compile which type body

       $type typemethod args...

       $type create name ?option value ...?

       $type info typevars ?pattern?

       $type info typemethods ?pattern?

       $type info args method

       $type info body method

       $type info default method aname varname

       $type info instances ?pattern?

       $type destroy

       $object method args...

       $object configure ?option? ?value? ...

       $object configurelist optionlist

       $object cget option

       $object destroy

       $object info type

       $object info vars ?pattern?

       $object info typevars ?pattern?

       $object info typemethods ?pattern?

       $object info options ?pattern?

       $object info methods ?pattern?

       $object info args method

       $object info body method

       $object info default method aname varname

       mymethod name ?args...?

       mytypemethod name ?args...?

       myproc name ?args...?

       myvar name

       mytypevar name

       from argvName option ?defvalue?

       install compName using objType objName args...

       installhull using widgetType args...

       installhull name

       variable name

       typevariable name

       varname name

       typevarname name

       codename name

       snit::boolean validate ?value?

       snit::boolean name

       snit::double validate ?value?

       snit::double name ?option value...?

       snit::enum validate ?value?

       snit::enum name ?option value...?

       snit::fpixels validate ?value?

       snit::fpixels name ?option value...?

       snit::integer validate ?value?

       snit::integer name ?option value...?

       snit::listtype validate ?value?

       snit::listtype name ?option value...?

       snit::pixels validate ?value?

       snit::pixels name ?option value...?

       snit::stringtype validate ?value?

       snit::stringtype name ?option value...?

       snit::window validate ?value?

       snit::window name

_________________________________________________________________________________________________

DESCRIPTION

       Snit  is a pure Tcl object and megawidget system.  It's unique among Tcl object systems in
       that it's based not on inheritance but on delegation.  Object systems based on inheritance
       only  allow  you to inherit from classes defined using the same system, which is limiting.
       In Tcl, an object is anything that acts like an object; it shouldn't matter how the object
       was  implemented.  Snit is intended to help you build applications out of the materials at
       hand; thus, Snit is designed to be able to incorporate and build on  any  object,  whether
       it's  a  hand-coded  object, a Tk widget, an Incr Tcl object, a BWidget or almost anything
       else.

       This man page is intended to be a reference only;  see  the  accompanying  snitfaq  for  a
       gentler, more tutorial introduction to Snit concepts.

SNIT VERSIONS

       This  man  page covers both Snit 2.2 and Snit 1.3.  The primary difference between the two
       versions is simply that Snit 2.2 contains speed optimizations based on new features of Tcl
       8.5;  Snit  1.3  supports  all  of  Tcl  8.3,  8.4  and  Tcl  8.5.   There are a few minor
       inconsistencies; they are flagged in the body of the man page with  the  label  "Snit  1.x
       Incompatibility"; they are also discussed in the snitfaq.

REFERENCE

   TYPE AND WIDGET DEFINITIONS
       Snit provides the following commands for defining new types:

       snit::type name definition
              Defines  a  new  abstract  data type called name.  If name is not a fully qualified
              command name, it is assumed to be a name in the namespace in which  the  snit::type
              command  was called (usually the global namespace).  It returns the fully qualified
              name of the new type.

              The type name is then a command that is used to create objects  of  the  new  type,
              along with other activities.

              The  snit::type  definition  block  is  a  script  that  may  contain the following
              definitions:

              typevariable name ?-array? ?value?
                     Defines a  type  variable  with  the  specified  name,  and  optionally  the
                     specified  value.   Type  variables are shared by all instances of the type.
                     If the -array option is included, then value should be a dictionary; it will
                     be assigned to the variable using array set.

              typemethod name arglist body
                     Defines  a  type  method,  a  subcommand  of  the new type command, with the
                     specified name, argument list, and  body.   The  arglist  is  a  normal  Tcl
                     argument  list  and  may  contain  default  arguments and the args argument;
                     however, it may not contain the argument names type, self, selfns, or win.

                     The variable type is automatically defined in the body to the type's  fully-
                     qualified  name.   In  addition, type variables are automatically visible in
                     the body of every type method.

                     If the name consists of two or more tokens, Snit handles it specially:

                         typemethod {a b} {arg} { puts "Got $arg" }

                     This statement implicitly defines  a  type  method  called  a  which  has  a
                     subcommand b.  b is called like this:

                         $type a b "Hello, world!"

                     a  may  have  any number of subcommands.  This makes it possible to define a
                     hierarchical command structure; see method, below, for more examples.

                     Type methods can call commands from the  namespace  in  which  the  type  is
                     defined    without   importing   them,   e.g.,   if   the   type   name   is
                     ::parentns::typename,   then   the   type's   type    methods    can    call
                     ::parentns::someproc  just as someproc.  Snit 1.x Incompatibility: This does
                     not work in Snit 1.x, as it depends on namespace path, a new command in  Tcl
                     8.5.

                     Snit  1.x Incompatibility: In Snit 1.x, the following following two calls to
                     this type method are equivalent:

                         $type a b "Hello, world!"
                         $type {a b} "Hello, world!"

                     In Snit 2.2, the second form is invalid.

              typeconstructor body
                     The type constructor's body is executed once when the type is first defined;
                     it  is  typically  used to initialize array-valued type variables and to add
                     entries to The Tk Option Database.

                     The variable type is automatically defined in the  body,  and  contains  the
                     type's  fully-qualified name.  In addition, type variables are automatically
                     visible in the body of the type constructor.

                     A type may define at most one type constructor.

                     The type constructor can call commands from the namespace in which the  type
                     is   defined   without   importing   them,   e.g.,   if  the  type  name  is
                     ::parentns::typename,    then    the    type    constructor     can     call
                     ::parentns::someproc  just as someproc.  Snit 1.x Incompatibility: This does
                     not work in Snit 1.x, as it depends on namespace path, a new command in  Tcl
                     8.5.

              variable name ?-array? ?value?
                     Defines  an  instance  variable,  a  private  variable  associated with each
                     instance of this type, and optionally its  initial  value.   If  the  -array
                     option  is  included, then value should be a dictionary; it will be assigned
                     to the variable using array set.

              method name arglist body
                     Defines an instance method, a subcommand of each instance of this type, with
                     the  specified  name,  argument  list and body.  The arglist is a normal Tcl
                     argument list and may contain default arguments and the args argument.

                     The method is implicitly passed the following arguments as well: type, which
                     contains  the  fully-qualified  type  name; self, which contains the current
                     instance command name; selfns, which contains the  name  of  the  instance's
                     private  namespace;  and  win,  which  contains  the original instance name.
                     Consequently, the arglist may not contain the  argument  names  type,  self,
                     selfns, or win.

                     An instance method defined in this way is said to be locally defined.

                     Type  and  instance  variables  are  automatically  visible  in all instance
                     methods.  If the type has locally defined options, the options array is also
                     visible.

                     If the name consists of two or more tokens, Snit handles it specially:

                         method {a b} {} { ... }

                     This  statement  implicitly defines a method called a which has a subcommand
                     b.  b is called like this:

                         $self a b "Hello, world!"

                     a may have any number of subcommands.  This makes it possible  to  define  a
                     hierarchical command structure:

                     % snit::type dog {
                         method {tail wag}   {} {return "Wag, wag"}
                         method {tail droop} {} {return "Droop, droop"}
                     }
                     ::dog
                     % dog spot
                     ::spot
                     % spot tail wag
                     Wag, wag
                     % spot tail droop
                     Droop, droop
                     %

                     What we've done is implicitly defined a "tail" method with subcommands "wag"
                     and "droop".  Consequently, it's an error to define "tail" explicitly.

                     Methods can call commands from the namespace in which the  type  is  defined
                     without importing them, e.g., if the type name is ::parentns::typename, then
                     the type's methods can call ::parentns::someproc just as someproc.  Snit 1.x
                     Incompatibility:  This does not work in Snit 1.x, as it depends on namespace
                     path, a new command in Tcl 8.5.

                     Snit 1.x Incompatibility: In Snit 1.x, the following following two calls  to
                     this method are equivalent:

                         $self a b "Hello, world!"
                         $self {a b} "Hello, world!"

                     In Snit 2.2, the second form is invalid.

              option namespec ?defaultValue?

              option namespec ?options...?
                     Defines  an  option  for  instances of this type, and optionally gives it an
                     initial value.  The initial  value  defaults  to  the  empty  string  if  no
                     defaultValue is specified.

                     An option defined in this way is said to be locally defined.

                     The  namespec is a list defining the option's name, resource name, and class
                     name, e.g.:

                         option {-font font Font} {Courier 12}

                     The option name must begin with a hyphen, and must  not  contain  any  upper
                     case  letters.  The  resource  name  and  class  name  are  optional; if not
                     specified, the resource name defaults to the option name, minus the  hyphen,
                     and  the  class  name  defaults  to  the resource name with the first letter
                     capitalized.  Thus, the following statement is equivalent  to  the  previous
                     example:

                         option -font {Courier 12}

                     See  The  Tk  Option  Database for more information about resource and class
                     names.

                     Options are normally set and retrieved using the standard  instance  methods
                     configure  and  cget;  within  instance  code  (method bodies, etc.), option
                     values are available through the options array:

                         set myfont $options(-font)

                     If the type defines any option handlers (e.g.,  -configuremethod),  then  it
                     should probably use configure and cget to access its options to avoid subtle
                     errors.

                     The option statement may include the following options:

                     -default defvalue
                            Defines the option's default value; the option's default  value  will
                            be "" otherwise.

                     -readonly flag
                            The  flag  can  be  any  Boolean value recognized by Tcl.  If flag is
                            true, then  the  option  is  read-only--it  can  only  be  set  using
                            configure  or  configurelist  at  creation  time, i.e., in the type's
                            constructor.

                     -type type
                            Every locally-defined option may define its  validation  type,  which
                            may  be either the name of a validation type or a specification for a
                            validation subtype

                            For example, an option may declare that its value must be an  integer
                            by specifying snit::integer as its validation type:

                                option -number -type snit::integer

                            It  may also declare that its value is an integer between 1 and 10 by
                            specifying a validation subtype:

                                option -number -type {snit::integer -min 1 -max 10}

                            If a validation type or subtype is defined for  an  option,  then  it
                            will be used to validate the option's value whenever it is changed by
                            the object's configure or configurelist methods.   In  addition,  all
                            such   options   will   have  their  values  validated  automatically
                            immediately after the constructor executes.

                            Snit defines a family of validation  types  and  subtypes,  and  it's
                            quite  simple  to  define  new  ones.   See  Validation Types for the
                            complete list, and Defining Validation Types for  an  explanation  of
                            how to define your own.

                     -cgetmethod methodName
                            Every  locally-defined  option may define a -cgetmethod; it is called
                            when the option's value is retrieved using the cget method.  Whatever
                            the  method's  body  returns  will be the return value of the call to
                            cget.

                            The named method must  take  one  argument,  the  option  name.   For
                            example,  this  code  is  equivalent  to  (though slower than) Snit's
                            default handling of cget:

                                option -font -cgetmethod GetOption
                                method GetOption {option} {
                                    return $options($option)
                                }

                            Note that it's  possible  for  any  number  of  options  to  share  a
                            -cgetmethod.

                     -configuremethod methodName
                            Every  locally-defined  option  may  define a -configuremethod; it is
                            called when  the  option's  value  is  set  using  the  configure  or
                            configurelist  methods.   It  is the named method's responsibility to
                            save the option's value; in other words, the value will not be  saved
                            to the options() array unless the method saves it there.

                            The named method must take two arguments, the option name and its new
                            value.  For example, this code is equivalent to (though slower  than)
                            Snit's default handling of configure:

                                option -font -configuremethod SetOption
                                method SetOption {option value} {
                                    set options($option) $value
                                }

                            Note  that  it's possible for any number of options to share a single
                            -configuremethod.

                     -validatemethod methodName
                            Every locally-defined option may  define  a  -validatemethod;  it  is
                            called  when  the  option's  value  is  set  using  the  configure or
                            configurelist methods, just before the -configuremethod (if any).  It
                            is  the  named  method's  responsibility to validate the option's new
                            value, and to throw an error if the value is invalid.

                            The named method must take two arguments, the option name and its new
                            value.  For example, this code verifies that -flag's value is a valid
                            Boolean value:

                                option -font -validatemethod CheckBoolean
                                method CheckBoolean {option value} {
                                    if {![string is boolean -strict $value]} {
                                        error "option $option must have a boolean value."
                                    }
                                }

                            Note that it's possible for any number of options to share  a  single
                            -validatemethod.

              constructor arglist body
                     The  constructor  definition  specifies a body of code to be executed when a
                     new instance is created.  The arglist is a normal Tcl argument list and  may
                     contain default arguments and the args argument.

                     As  with  methods,  the  arguments  type,  self, selfns, and win are defined
                     implicitly, and all type and instance variables are automatically visible in
                     its body.

                     If  the  definition  doesn't explicitly define the constructor, Snit defines
                     one implicitly.  If the type declares at least one option  (whether  locally
                     or by delegation), the default constructor will be defined as follows:

                         constructor {args} {
                             $self configurelist $args
                         }

                     For standard Tk widget behavior, the argument list should be the single name
                     args, as shown.

                     If the definition defines neither a constructor nor any options, the default
                     constructor is defined as follows:

                         constructor {} {}

                     As  with  methods,  the  constructor can call commands from the namespace in
                     which the type is defined without importing them, e.g., if the type name  is
                     ::parentns::typename,  then  the  constructor  can call ::parentns::someproc
                     just as someproc.  Snit 1.x Incompatibility: This does not work in Snit 1.x,
                     as it depends on namespace path, a new command in Tcl 8.5.

              destructor body
                     The  destructor  is  used  to  code any actions that must take place when an
                     instance of the type is destroyed: typically, the  destruction  of  anything
                     created in the constructor.

                     The  destructor  takes no explicit arguments; as with methods, the arguments
                     type, self, selfns, and win,  are  defined  implicitly,  and  all  type  and
                     instance  variables are automatically visible in its body.  As with methods,
                     the destructor can call commands from the namespace in  which  the  type  is
                     defined    without   importing   them,   e.g.,   if   the   type   name   is
                     ::parentns::typename, then the destructor can call ::parentns::someproc just
                     as  someproc.   Snit 1.x Incompatibility: This does not work in Snit 1.x, as
                     it depends on namespace path, a new command in Tcl 8.5.

              proc name args body
                     Defines a new Tcl procedure in the type's namespace.

                     The defined proc differs from a normal Tcl proc in that all  type  variables
                     are  automatically visible.  The proc can access instance variables as well,
                     provided that it is passed selfns (with precisely that name) as one  of  its
                     arguments.

                     Although they are not implicitly defined for procs, the argument names type,
                     self, and win should be avoided.

                     As with methods and typemethods, procs can call commands from the  namespace
                     in  which the type is defined without importing them, e.g., if the type name
                     is ::parentns::typename, then the proc can call ::parentns::someproc just as
                     someproc.   Snit  1.x Incompatibility: This does not work in Snit 1.x, as it
                     depends on namespace path, a new command in Tcl 8.5.

              delegate method name to comp ?as target?
                     Delegates method name to component comp.   That  is,  when  method  name  is
                     called  on  an  instance  of this type, the method and its arguments will be
                     passed to the named component's command instead.   That  is,  the  following
                     statement

                         delegate method wag to tail

                     is roughly equivalent to this explicitly defined method:

                         method wag {args} {
                             uplevel $tail wag $args
                         }

                     As  with  methods, the name may have multiple tokens; in this case, the last
                     token of the name is assumed to be the name of the component's method.

                     The optional as clause allows you to specify the delegated method  name  and
                     possibly add some arguments:

                         delegate method wagtail to tail as "wag briskly"

              A method cannot be both locally defined and delegated.

              Note:  All  forms  of  delegate method can delegate to both instance components and
              type components.

              delegate method name ?to comp? using pattern
                     In this form of the delegate statement, the using clause is used to  specify
                     the  precise form of the command to which method name name is delegated.  In
                     this form, the to clause is optional, since the  chosen  command  might  not
                     involve any particular component.

                     The  value  of the using clause is a list that may contain any or all of the
                     following substitution codes; these codes are substituted with the described
                     value  to  build  the delegated command prefix.  Note that the following two
                     statements are equivalent:

                         delegate method wag to tail
                         delegate method wag to tail using "%c %m"

                     Each element  of  the  list  becomes  a  single  element  of  the  delegated
                     command--it is never reparsed as a string.

                     Substitutions:

                     %%     This is replaced with a single "%".  Thus, to pass the string "%c" to
                            the command as an argument, you'd write "%%c".

                     %c     This is replaced with the named component's command.

                     %m     This is replaced with the final token of  the  method  name;  if  the
                            method name has one token, this is identical to %M.

                     %M     This is replaced by the method name; if the name consists of multiple
                            tokens, they are joined by space characters.

                     %j     This is replaced by the method name; if the name consists of multiple
                            tokens, they are joined by underscores ("_").

                     %t     This is replaced with the fully qualified type name.

                     %n     This is replaced with the name of the instance's private namespace.

                     %s     This is replaced with the name of the instance command.

                     %w     This  is replaced with the original name of the instance command; for
                            Snit widgets and widget adaptors, it will be the Tk window name.   It
                            remains constant, even if the instance command is renamed.

              delegate method * ?to comp? ?using pattern? ?except exceptions?
                     The  form  delegate  method  *  delegates  all  unknown  method names to the
                     specified component.  The except clause can be used to  specify  a  list  of
                     exceptions,  i.e.,  method  names  that  will not be so delegated. The using
                     clause is defined as given above.  In this form, the statement must  contain
                     the to clause, the using clause, or both.

                     In  fact,  the "*" can be a list of two or more tokens whose last element is
                     "*", as in the following example:

                         delegate method {tail *} to tail

                     This implicitly defines the method tail whose subcommands will be  delegated
                     to the tail component.

              delegate option namespec to comp

              delegate option namespec to comp as target

              delegate option * to comp

              delegate option * to comp except exceptions
                     Defines  a  delegated  option;  the  namespec  is  defined as for the option
                     statement.  When the configure, configurelist, or cget  instance  method  is
                     used to set or retrieve the option's value, the equivalent configure or cget
                     command will be applied to the component as though the  option  was  defined
                     with the following -configuremethod and -cgetmethod:

                         method ConfigureMethod {option value} {
                             $comp configure $option $value
                         }

                         method CgetMethod {option} {
                             return [$comp cget $option]
                         }

                     Note that delegated options never appear in the options array.

                     If  the as clause is specified, then the target option name is used in place
                     of name.

                     The form delegate option * delegates all unknown options  to  the  specified
                     component.   The  except clause can be used to specify a list of exceptions,
                     i.e., option names that will not be so delegated.

                     Warning: options can only be delegated to a component  if  it  supports  the
                     configure and cget instance methods.

                     An  option cannot be both locally defined and delegated.  TBD: Continue from
                     here.

              component comp ?-public method? ?-inherit flag?
                     Explicitly declares a component called comp, and automatically  defines  the
                     component's instance variable.

                     If  the  -public  option  is  specified,  then  the option is made public by
                     defining a method whose subcommands are delegated  to  the  component  e.g.,
                     specifying -public mycomp is equivalent to the following:

                         component mycomp
                         delegate method {mymethod *} to mycomp

                     If  the  -inherit option is specified, then flag must be a Boolean value; if
                     flag is true then all unknown methods and options will be delegated to  this
                     component.   The  name  -inherit  implies  that  instances  of this new type
                     inherit, in a sense, the methods and options  of  the  component.  That  is,
                     -inherit yes is equivalent to:

                         component mycomp
                         delegate option * to mycomp
                         delegate method * to mycomp

              delegate typemethod name to comp ?as target?
                     Delegates  type  method  name  to  type  component comp.  That is, when type
                     method name is called on this type, the type method and its  arguments  will
                     be  passed  to  the  named  type  component's command instead.  That is, the
                     following statement

                         delegate typemethod lostdogs to pound

                     is roughly equivalent to this explicitly defined method:

                         typemethod lostdogs {args} {
                             uplevel $pound lostdogs $args
                         }

                     As with type methods, the name may have multiple tokens; in this  case,  the
                     last token of the name is assumed to be the name of the component's method.

                     The  optional  as clause allows you to specify the delegated method name and
                     possibly add some arguments:

                         delegate typemethod lostdogs to pound as "get lostdogs"

              A type method cannot be both locally defined and delegated.

              delegate typemethod name ?to comp? using pattern
                     In this form of the delegate statement, the using clause is used to  specify
                     the precise form of the command to which type method name name is delegated.
                     In this form, the to clause is optional, since the chosen command might  not
                     involve any particular type component.

                     The  value  of the using clause is a list that may contain any or all of the
                     following substitution codes; these codes are substituted with the described
                     value  to  build  the delegated command prefix.  Note that the following two
                     statements are equivalent:

                         delegate typemethod lostdogs to pound
                         delegate typemethod lostdogs to pound using "%c %m"

                     Each element  of  the  list  becomes  a  single  element  of  the  delegated
                     command--it is never reparsed as a string.

                     Substitutions:

                     %%     This is replaced with a single "%".  Thus, to pass the string "%c" to
                            the command as an argument, you'd write "%%c".

                     %c     This is replaced with the named type component's command.

                     %m     This is replaced with the final token of the type method name; if the
                            type method name has one token, this is identical to %M.

                     %M     This  is  replaced  by  the type method name; if the name consists of
                            multiple tokens, they are joined by space characters.

                     %j     This is replaced by the type method name; if  the  name  consists  of
                            multiple tokens, they are joined by underscores ("_").

                     %t     This is replaced with the fully qualified type name.

              delegate typemethod * ?to comp? ?using pattern? ?except exceptions?
                     The  form  delegate  typemethod * delegates all unknown type method names to
                     the specified type component.  The except clause can be used  to  specify  a
                     list  of  exceptions, i.e., type method names that will not be so delegated.
                     The using clause is defined as given above.  In  this  form,  the  statement
                     must contain the to clause, the using clause, or both.

                     Note: By default, Snit interprets $type foo, where foo is not a defined type
                     method, as equivalent to $type create foo, where foo is the name  of  a  new
                     instance  of  the  type.   If you use delegate typemethod *, then the create
                     type method must always be used explicitly.

                     The "*" can be a list of two or more tokens whose last element is "*", as in
                     the following example:

                         delegate typemethod {tail *} to tail

                     This  implicitly  defines  the  type  method  tail whose subcommands will be
                     delegated to the tail type component.

              typecomponent comp ?-public typemethod? ?-inherit flag?
                     Explicitly declares a type component called comp, and automatically  defines
                     the  component's type variable.  A type component is an arbitrary command to
                     which type methods and instance methods can be delegated; the command's name
                     is stored in a type variable.

                     If  the  -public option is specified, then the type component is made public
                     by defining a  typemethod  whose  subcommands  are  delegated  to  the  type
                     component,  e.g.,  specifying  -public  mytypemethod  is  equivalent  to the
                     following:

                         typecomponent mycomp
                         delegate typemethod {mytypemethod *} to mycomp

                     If the -inherit option is specified, then flag must be a Boolean  value;  if
                     flag  is  true  then all unknown type methods will be delegated to this type
                     component. (See the note  on  "delegate  typemethod  *",  above.)  The  name
                     -inherit  implies  that  this type inherits, in a sense, the behavior of the
                     type component. That is, -inherit yes is equivalent to:

                         typecomponent mycomp
                         delegate typemethod * to mycomp

              pragma ?options...?
                     The pragma statement provides control over how Snit generates  a  type.   It
                     takes  the  following  options;  in  each case, flag must be a Boolean value
                     recognized by Tcl, e.g., 0, 1, yes, no, and so on.

                     By setting the -hastypeinfo, -hastypedestroy, and -hasinstances  pragmas  to
                     false  and  defining  appropriate  type  methods, you can create an ensemble
                     command without any extraneous behavior.

                     -canreplace flag
                            If false (the  default)  Snit  will  not  create  an  instance  of  a
                            snit::type  that  has  the  same  name  as  an existing command; this
                            prevents subtle errors.  Setting this pragma  to  true  restores  the
                            behavior of Snit V0.93 and earlier versions.

                     -hastypeinfo flag
                            If  true  (the  default),  the generated type will have a type method
                            called info that is used for type introspection; the info type method
                            is documented below.  If false, it will not.

                     -hastypedestroy flag
                            If  true  (the  default),  the generated type will have a type method
                            called destroy that is used to  destroy  the  type  and  all  of  its
                            instances.   The  destroy type method is documented below.  If false,
                            it will not.

                     -hastypemethods flag
                            If true (the default), the generated type's type  command  will  have
                            subcommands (type methods) as usual.  If false, the type command will
                            serve only to create instances of the type; the first argument is the
                            instance name.

                            This pragma and -hasinstances cannot both be set false.

                     -hasinstances flag
                            If  true  (the  default),  the generated type will have a type method
                            called create that is used to create instances  of  the  type,  along
                            with a variety of instance-related features.  If false, it will not.

                            This pragma and -hastypemethods cannot both be set false.

                     -hasinfo flag
                            If  true  (the default), instances of the generated type will have an
                            instance method called info that is used for instance  introspection;
                            the info method is documented below.  If false, it will not.

                     -simpledispatch flag
                            This  pragma  is  intended to make simple, heavily-used abstract data
                            types (e.g., stacks and queues) more efficient.

                            If false (the default), instance methods are dispatched normally.  If
                            true,  a  faster dispatching scheme is used instead.  The speed comes
                            at  a  price;  with  -simpledispatch  yes  you  get   the   following
                            limitations:

                            •      Methods cannot be delegated.

                            •      uplevel  and upvar do not work as expected: the caller's scope
                                   is two levels up rather than one.

                            •      The   option-handling   methods    (cget,    configure,    and
                                   configurelist) are very slightly slower.

              expose comp

              expose comp as method
                     Deprecated.   To  expose  component  comp  publicly, use component's -public
                     option.

              onconfigure name arglist body
                     Deprecated.  Define option's -configuremethod option instead.

                     As of version 0.95, the following definitions,

                         option -myoption
                         onconfigure -myoption {value} {
                             # Code to save the option's value
                         }

                     are implemented as follows:

                         option -myoption -configuremethod _configure-myoption
                         method _configure-myoption {_option value} {
                             # Code to save the option's value
                         }

              oncget name body
                     Deprecated.  Define option's -cgetmethod option instead.

                     As of version 0.95, the following definitions,

                         option -myoption
                         oncget -myoption {
                             # Code to return the option's value
                         }

                     are implemented as follows:

                         option -myoption -cgetmethod _cget-myoption
                         method _cget-myoption {_option} {
                             # Code to return the option's value
                         }

       snit::widget name definition
              This command  defines  a  Snit  megawidget  type  with  the  specified  name.   The
              definition  is defined as for snit::type.  A snit::widget differs from a snit::type
              in these ways:

              •      Every instance of a  snit::widget  has  an  automatically-created  component
                     called  hull, which is normally a Tk frame widget.  Other widgets created as
                     part of the megawidget will be created within this widget.

                     The hull component is initially created with the requested widget name; then
                     Snit  does  some  magic,  renaming the hull component and installing its own
                     instance command in its place.  The hull component's new name is saved in an
                     instance variable called hull.

              •      The  name of an instance must be valid Tk window name, and the parent window
                     must exist.

              A snit::widget definition can include any of statements  allowed  in  a  snit::type
              definition, and may also include the following:

              widgetclass name
                     Sets  the  snit::widget's widget class to name, overriding the default.  See
                     The Tk Option Database for more information.

              hulltype type
                     Determines the kind of widget used as the snit::widget's hull.  The type may
                     be  frame  (the default), toplevel, labelframe; the qualified equivalents of
                     these, tk::frame, tk::toplevel, and tk::labelframe; or,  if  available,  the
                     equivalent Tile widgets: ttk::frame, ttk::toplevel, and ttk::labelframe.  In
                     practice, any widget that supports the -class option can be used as  a  hull
                     widget by lappend'ing its name to the variable snit::hulltypes.

       snit::widgetadaptor name definition
              This  command  defines  a Snit megawidget type with the specified name.  It differs
              from  snit::widget  in  that  the  instance's  hull  component   is   not   created
              automatically,   but  is  created  in  the  constructor  and  installed  using  the
              installhull command.  Once the hull is installed, its instance command  is  renamed
              and  replaced  as  with  normal  snit::widgets.   The  original  command  is  again
              accessible in the instance variable hull.

              Note that in  general  it  is  not  possible  to  change  the  widget  class  of  a
              snit::widgetadaptor's hull widget.

              See  The  Tk  Option  Database for information on how snit::widgetadaptors interact
              with the option database.

       snit::typemethod type name arglist body
              Defines a new type method (or redefines an existing type method) for  a  previously
              existing type.

       snit::method type name arglist body
              Defines  a  new  instance  method  (or redefines an existing instance method) for a
              previously existing type.  Note that delegated instance methods can't be redefined.

       snit::macro name arglist body
              Defines a Snit macro with the specified name, arglist, and body.  Macros  are  used
              to  define  new  type  and  widget definition statements in terms of the statements
              defined in this man page.

              A macro is simply a Tcl proc that is defined  in  the  slave  interpreter  used  to
              compile  type  and widget definitions.  Thus, macros have access to all of the type
              and widget  definition  statements.   See  Macros  and  Meta-programming  for  more
              details.

              The  macro name cannot be the same as any standard Tcl command, or any Snit type or
              widget definition statement, e.g.,  you  can't  redefine  the  method  or  delegate
              statements, or the standard set, list, or string commands.

       snit::compile which type body
              Snit  defines a type, widget, or widgetadaptor by "compiling" the definition into a
              Tcl script; this script is then evaluated in the Tcl  interpreter,  which  actually
              defines the new type.

              This  command  exposes the "compiler".  Given a definition body for the named type,
              where which is type, widget, or widgetadaptor, snit::compile returns a list of  two
              elements.   The  first element is the fully qualified type name; the second element
              is the definition script.

              snit::compile is useful when additional  processing  must  be  done  on  the  Snit-
              generated  code--if  it  must  be  instrumented,  for  example,  or run through the
              TclDevKit compiler.  In addition, the returned script could be saved  in  a  ".tcl"
              file  and used to define the type as part of an application or library, thus saving
              the compilation overhead at application start-up.  Note that the  same  version  of
              Snit must be used at run-time as at compile-time.

   THE TYPE COMMAND
       A  type  or widget definition creates a type command, which is used to create instances of
       the type.  The type command has this form:

       $type typemethod args...
              The typemethod can be any of the Standard Type Methods (e.g., create), or any  type
              method  defined in the type definition.  The subsequent args depend on the specific
              typemethod chosen.

              The type command is most often used to create new instances of the type; hence, the
              create  method  is assumed if the first argument to the type command doesn't name a
              valid type method, unless the type definition includes delegate typemethod * or the
              -hasinstances pragma is set to false.

              Furthermore, if the -hastypemethods pragma is false, then Snit type commands can be
              called with no arguments at all; in this case, the type command creates an instance
              with   an  automatically  generated  name.   In  other  words,  provided  that  the
              -hastypemethods pragma is false and the type has instances, the following  commands
              are equivalent:

              snit::type dog { ... }

              set mydog [dog create %AUTO%]
              set mydog [dog %AUTO%]
              set mydog [dog]

              This doesn't work for Snit widgets, for obvious reasons.

              Snit  1.x  Incompatibility:  In  Snit  1.x, the above behavior is available whether
              -hastypemethods is true (the default) or false.

   STANDARD TYPE METHODS
       In addition to any type methods in the type's definition, all  type  and  widget  commands
       will usually have at least the following subcommands:

       $type create name ?option value ...?
              Creates  a  new  instance of the type, giving it the specified name and calling the
              type's constructor.

              For snit::types, if name is not a fully-qualified command name, it is assumed to be
              a  name  in  the  namespace  in  which  the call to snit::type appears.  The method
              returns the fully-qualified instance name.

              For snit::widgets and snit::widgetadaptors, name must be a valid widget  name;  the
              method returns the widget name.

              So  long  as  name  does  not conflict with any defined type method name the create
              keyword may be omitted, unless the type definition includes delegate  typemethod  *
              or the -hasinstances pragma is set to false.

              If  the  name  includes  the  string  %AUTO%,  it  will be replaced with the string
              $type$counter where $type  is  the  type  name  and  $counter  is  a  counter  that
              increments each time %AUTO% is used for this type.

              By  default,  any  arguments  following the name will be a list of option names and
              their values; however, a type's constructor can specify a different argument list.

              As of Snit V0.95, create will throw an error  if  the  name  is  the  same  as  any
              existing   command--note   that   this   was  always  true  for  snit::widgets  and
              snit::widgetadaptors.  You can restore the previous behavior using the  -canreplace
              pragma.

       $type info typevars ?pattern?
              Returns  a  list  of the type's type variables (excluding Snit internal variables);
              all variable names are fully-qualified.

              If pattern is given, it's used as a string match pattern; only names that match the
              pattern are returned.

       $type info typemethods ?pattern?
              Returns  a  list  of  the  names  of  the   type's  type  methods.  If the type has
              hierarchical type methods, whether locally-defined or  delegated,  only  the  first
              word of each will be included in the list.

              If  the  type definition includes delegate typemethod *, the list will include only
              the names of those implicitly delegated type methods that have been called at least
              once and are still in the type method cache.

              If pattern is given, it's used as a string match pattern; only names that match the
              pattern are returned.

       $type info args method
              Returns a list containing the names of the  arguments  to  the  type's  method,  in
              order. This method cannot be applied to delegated type methods.

       $type info body method
              Returns  the  body of typemethod method. This method cannot be applied to delegated
              type methods.

       $type info default method aname varname
              Returns a boolean value indicating whether the argument aname of the type's  method
              has  a default value (true) or not (false). If the argument has a default its value
              is placed into the variable varname.

       $type info instances ?pattern?
              Returns a list of the type's instances.  For snit::types, it  will  be  a  list  of
              fully-qualified  instance  names; for snit::widgets, it will be a list of Tk widget
              names.

              If pattern is given, it's used as a string match pattern; only names that match the
              pattern are returned.

              Snit  1.x  Incompatibility:  In Snit 1.x, the full multi-word names of hierarchical
              type methods are included in the return value.

       $type destroy
              Destroys the type's instances, the type's namespace, and the type command itself.

   THE INSTANCE COMMAND
       A Snit type or widget's create type method creates objects of the type; each object has  a
       unique  name  that  is  also  a  Tcl command.  This command is used to access the object's
       methods and data, and has this form:

       $object method args...
              The method can be any of the Standard Instance  Methods,  or  any  instance  method
              defined  in the type definition.  The subsequent args depend on the specific method
              chosen.

   STANDARD INSTANCE METHODS
       In addition to any delegated or locally-defined instance methods in the type's definition,
       all Snit objects will have at least the following subcommands:

       $object configure ?option? ?value? ...
              Assigns  new values to one or more options.  If called with one argument, an option
              name, returns a list describing the option, as Tk widgets do;  if  called  with  no
              arguments, returns a list of lists describing all options, as Tk widgets do.

              Warning:  This  information  will  be  available  for delegated options only if the
              component to which they are delegated has a configure method that returns this same
              kind of information.

              Note: Snit defines this method only if the type has at least one option.

       $object configurelist optionlist
              Like  configure,  but takes one argument, a list of options and their values.  It's
              mostly useful in the type constructor, but can be used anywhere.

              Note: Snit defines this method only if the type has at least one option.

       $object cget option
              Returns the option's value.

              Note: Snit defines this method only if the type has at least one option.

       $object destroy
              Destroys the object, calling the destructor and freeing all related memory.

              Note: The destroy method isn't  defined  for  snit::widget  or  snit::widgetadaptor
              objects;  instances of these are destroyed by calling Tk's destroy command, just as
              normal widgets are.

       $object info type
              Returns the instance's type.

       $object info vars ?pattern?
              Returns a  list  of  the  object's  instance  variables  (excluding  Snit  internal
              variables).  The names are fully qualified.

              If pattern is given, it's used as a string match pattern; only names that match the
              pattern are returned.

       $object info typevars ?pattern?
              Returns a list of the object's  type's  type  variables  (excluding  Snit  internal
              variables).  The names are fully qualified.

              If pattern is given, it's used as a string match pattern; only names that match the
              pattern are returned.

       $object info typemethods ?pattern?
              Returns a list of the  names  of  the   type's  type  methods.   If  the  type  has
              hierarchical  type  methods,  whether  locally-defined or delegated, only the first
              word of each will be included in the list.

              If the type definition includes delegate typemethod *, the list will  include  only
              the names of those implicitly delegated type methods that have been called at least
              once and are still in the type method cache.

              If pattern is given, it's used as a string match pattern; only names that match the
              pattern are returned.

              Snit  1.x  Incompatibility:  In Snit 1.x, the full multi-word names of hierarchical
              type methods are included in the return value.

       $object info options ?pattern?
              Returns a list of the object's option names.  This always  includes  local  options
              and explicitly delegated options.  If unknown options are delegated as well, and if
              the component to which they are delegated responds to  $object  configure  like  Tk
              widgets  do,  then the result will include all possible unknown options that can be
              delegated to the component.

              If pattern is given, it's used as a string match pattern; only names that match the
              pattern are returned.

              Note  that  the return value might be different for different instances of the same
              type, if component object types can vary from one instance to another.

       $object info methods ?pattern?
              Returns a  list  of  the  names  of  the  instance's  methods.   If  the  type  has
              hierarchical  methods, whether locally-defined or delegated, only the first word of
              each will be included in the list.

              If the type definition includes delegate method *, the list will include  only  the
              names of those implicitly delegated methods that have been called at least once and
              are still in the method cache.

              If pattern is given, it's used as a string match pattern; only names that match the
              pattern are returned.

              Snit  1.x  Incompatibility:  In Snit 1.x, the full multi-word names of hierarchical
              type methods are included in the return value.

       $object info args method
              Returns a list containing the names of the arguments to the instance's  method,  in
              order. This method cannot be applied to delegated methods.

       $object info body method
              Returns  the body of the instance's method method. This method cannot be applied to
              delegated methods.

       $object info default method aname varname
              Returns a boolean value indicating whether the argument  aname  of  the  instance's
              method has a default value (true) or not (false). If the argument has a default its
              value is placed into the variable varname.

   COMMANDS FOR USE IN OBJECT CODE
       Snit defines the following commands for use in your object code: that is, for use in  type
       methods,   instance  methods,  constructors,  destructors,  onconfigure  handlers,  oncget
       handlers, and procs.  They do not reside in the  ::snit::  namespace;  instead,  they  are
       created with the type, and can be used without qualification.

       mymethod name ?args...?
              The mymethod command is used for formatting callback commands to be passed to other
              objects.  It returns a command that when called will invoke method  name  with  the
              specified  arguments,  plus  of course any arguments added by the caller.  In other
              words, both of the following commands will cause the object's dosomething method to
              be called when the $button is pressed:

                  $button configure -command [list $self dosomething myargument]

                  $button configure -command [mymethod dosomething myargument]

              The chief distinction between the two is that the latter form will not break if the
              object's command is renamed.

       mytypemethod name ?args...?
              The mytypemethod command is used for formatting callback commands to be  passed  to
              other  objects.  It returns a command that when called will invoke type method name
              with the specified arguments, plus of course any arguments added by the caller.  In
              other  words,  both  of  the following commands will cause the object's dosomething
              type method to be called when $button is pressed:

                  $button configure -command [list $type dosomething myargument]

                  $button configure -command [mytypemethod dosomething myargument]

              Type commands cannot be renamed, so in practice there's little  difference  between
              the two forms.  mytypemethod is provided for parallelism with mymethod.

       myproc name ?args...?
              The  myproc  command is used for formatting callback commands to be passed to other
              objects.  It returns a command that when called will invoke the type proc name with
              the  specified  arguments,  plus  of  course any arguments added by the caller.  In
              other words, both of the following commands will  cause  the  object's  dosomething
              proc to be called when $button is pressed:

                  $button configure -command [list ${type}::dosomething myargument]

                  $button configure -command [myproc dosomething myargument]

       myvar name
              Given  an  instance  variable  name, returns the fully qualified name.  Use this if
              you're passing the variable to some other object, e.g., as a -textvariable to a  Tk
              label widget.

       mytypevar name
              Given  an type variable name, returns the fully qualified name.  Use this if you're
              passing the variable to some other object, e.g., as a -textvariable to a  Tk  label
              widget.

       from argvName option ?defvalue?
              The  from  command  plucks an option value from a list of options and their values,
              such as is passed into a type's constructor.   argvName  must  be  the  name  of  a
              variable containing such a list; option is the name of the specific option.

              from  looks  for  option  in the option list.  If it is found, it and its value are
              removed from the list, and the value is returned.  If option doesn't appear in  the
              list,  then the defvalue is returned.  If the option is locally-defined option, and
              defvalue is not specified, then the option's default value as specified in the type
              definition will be returned instead.

       install compName using objType objName args...
              Creates  a  new  object of type objType called objName and installs it as component
              compName, as described in Components and Delegation.  Any  additional  args...  are
              passed  along  with the name to the objType command.  If this is a snit::type, then
              the following two commands are equivalent:

                  install myComp using myObjType $self.myComp args...

                  set myComp [myObjType $self.myComp args...]

              Note that whichever method is used, compName must still be  declared  in  the  type
              definition  using  component,  or  must  be  referenced  in  at  least one delegate
              statement.

              If this is  a  snit::widget  or  snit::widgetadaptor,  and  if  options  have  been
              delegated  to  component  compName,  then those options will receive default values
              from the Tk option database.  Note that it doesn't matter whether the component  to
              be installed is a widget or not.  See The Tk Option Database for more information.

              install cannot be used to install type components; just assign the type component's
              command name to the type component's variable instead.

       installhull using widgetType args...

       installhull name
              The constructor of a snit::widgetadaptor must create a widget to  be  the  object's
              hull  component;  the widget is installed as the hull component using this command.
              Note that the installed widget's name must be $win.  This command has two forms.

              The first form specifies the widgetType and the args...  (that  is,  the  hardcoded
              option list) to use in creating the hull.  Given this form, installhull creates the
              hull widget, and initializes any options delegated to the hull from the  Tk  option
              database.

              In  the  second  form, the hull widget has already been created; note that its name
              must be "$win".  In this case, the Tk  option  database  is  not  queried  for  any
              options  delegated to the hull.  The longer form is preferred; however, the shorter
              form allows the programmer to adapt a widget created elsewhere, which is  sometimes
              useful.  For example, it can be used to adapt a "page" widget created by a BWidgets
              tabbed notebook or pages manager widget.

              See The Tk Option Database for more information about snit::widgetadaptors and  the
              option database.

       variable name
              Normally,  instance  variables  are  defined  in the type definition along with the
              options, methods, and so forth; such instance variables are  automatically  visible
              in  all  instance  code  (e.g., method bodies).  However, instance code can use the
              variable command to declare instance  variables  that  don't  appear  in  the  type
              definition,  and  also  to  bring variables from other namespaces into scope in the
              usual way.

              It's generally clearest to define all instance variables in  the  type  definition,
              and omit declaring them in methods and so forth.

              Note  that  this  is  an  instance-specific  version of the standard Tcl ::variable
              command.

       typevariable name
              Normally, type variables are  defined  in  the  type  definition,  along  with  the
              instance  variables;  such  type  variables are automatically visible in all of the
              type's code.  However,  type  methods,  instance  methods  and  so  forth  can  use
              typevariable to declare type variables that don't appear in the type definition.

              It's  generally  clearest to declare all type variables in the type definition, and
              omit declaring them in methods, type methods, etc.

       varname name
              Deprecated.  Use myvar instead.

              Given an instance variable name, returns the fully qualified  name.   Use  this  if
              you're  passing the variable to some other object, e.g., as a -textvariable to a Tk
              label widget.

       typevarname name
              Deprecated.  Use mytypevar instead.

              Given a type variable name, returns the fully qualified name.  Use this  if  you're
              passing  the  type  variable to some other object, e.g., as a -textvariable to a Tk
              label widget.

       codename name
              Deprecated.  Use myproc instead.  Given the name of a  proc  (but  not  a  type  or
              instance method), returns the fully-qualified command name, suitable for passing as
              a callback.

   COMPONENTS AND DELEGATION
       When an object includes other objects, as when a toolbar contains buttons or a GUI  object
       contains  an object that references a database, the included object is called a component.
       The standard way to handle component objects owned by a Snit object  is  to  declare  them
       using component, which creates a component instance variable.  In the following example, a
       dog object has a tail object:

                  snit::type dog {
                      component mytail

                      constructor {args} {
                          set mytail [tail %AUTO% -partof $self]
                          $self configurelist $args
                      }

                      method wag {} {
                          $mytail wag
                      }
                  }

                  snit::type tail {
                      option -length 5
                      option -partof
                      method wag {} { return "Wag, wag, wag."}
                  }

       Because the tail object's name is stored in an instance variable, it's  easily  accessible
       in any method.

       The install command provides an alternate way to create and install the component:

                  snit::type dog {
                      component mytail

                      constructor {args} {
                          install mytail using tail %AUTO% -partof $self
                          $self configurelist $args
                      }

                      method wag {} {
                          $mytail wag
                      }
                  }

       For    snit::types,    the   two   methods   are   equivalent;   for   snit::widgets   and
       snit::widgetadaptors, the install command properly initializes  the  widget's  options  by
       querying The Tk Option Database.

       In  the  above examples, the dog object's wag method simply calls the tail component's wag
       method.  In OO jargon, this is called delegation.  Snit provides an easier way to do this:

                  snit::type dog {
                      delegate method wag to mytail

                      constructor {args} {
                          install mytail using tail %AUTO% -partof $self
                          $self configurelist $args
                      }
                  }

       The delegate statement in the type definition implicitly  defines  the  instance  variable
       mytail  to hold the component's name (though it's good form to use component to declare it
       explicitly); it also defines the dog object's wag method,  delegating  it  to  the  mytail
       component.

       If desired, all otherwise unknown methods can be delegated to a specific component:

                  snit::type dog {
                delegate method * to mytail

                constructor {args} {
                    set mytail [tail %AUTO% -partof $self]
                    $self configurelist $args
                }

                method bark { return "Bark, bark, bark!" }
                  }

       In  this  case, a dog object will handle its own bark method; but wag will be passed along
       to mytail.  Any other method, being recognized by neither dog nor tail, will simply  raise
       an error.

       Option delegation is similar to method delegation, except for the interactions with the Tk
       option database; this is described in The Tk Option Database.

   TYPE COMPONENTS AND DELEGATION
       The relationship between type components and instance  components  is  identical  to  that
       between  type variables and instance variables, and that between type methods and instance
       methods.  Just as an instance component is an instance variable that holds the name  of  a
       command,  so  a  type  component  is a type variable that holds the name of a command.  In
       essence, a type component is a component that's shared by every instance of the type.

       Just as delegate method can be  used  to  delegate  methods  to  instance  components,  as
       described  in  Components  and  Delegation, so delegate typemethod can be used to delegate
       type methods to type components.

       Note also that as of Snit 0.95 delegate method  can  delegate  methods  to  both  instance
       components and type components.

   THE TK OPTION DATABASE
       This  section  describes  how  Snit interacts with the Tk option database, and assumes the
       reader has a working knowledge of the option database and its uses.   The  book  Practical
       Programming  in  Tcl and Tk by Welch et al has a good introduction to the option database,
       as does Effective Tcl/Tk Programming.

       Snit is implemented so that most of the time it  will  simply  do  the  right  thing  with
       respect to the option database, provided that the widget developer does the right thing by
       Snit.  The body of this section goes into  great  deal  about  what  Snit  requires.   The
       following is a brief statement of the requirements, for reference.

       •      If  the  snit::widget's  default  widget  class  is  not  what  is  desired, set it
              explicitly using widgetclass in the widget definition.

       •      When  defining  or  delegating  options,  specify  the  resource  and  class  names
              explicitly when if the defaults aren't what you want.

       •      Use installhull using to install the hull for snit::widgetadaptors.

       •      Use install to install all other components.

       The interaction of Tk widgets with the option database is a complex thing; the interaction
       of Snit with the option database is even more so, and repays attention to detail.

       Setting the widget class: Every Tk widget has a widget class.  For Tk widgets, the  widget
       class  name  is  the  just  the widget type name with an initial capital letter, e.g., the
       widget class for button widgets is "Button".

       Similarly, the widget class of a snit::widget defaults to the unqualified type  name  with
       the first letter capitalized.  For example, the widget class of

                  snit::widget ::mylibrary::scrolledText { ... }

       is  "ScrolledText".   The  widget  class  can also be set explicitly using the widgetclass
       statement within the snit::widget definition.

       Any widget can be used as the hulltype provided that it supports  the  -class  option  for
       changing  its  widget class name.  See the discussion of the hulltype command, above.  The
       user may pass -class to the widget at instantion.

       The widget class of a snit::widgetadaptor is just the widget class  of  its  hull  widget;
       this  cannot  be  changed  unless  the  hull widget supports -class, in which case it will
       usually make more sense to use snit::widget rather than snit::widgetadaptor.

       Setting option resource names and classes: In Tk, every option has three names: the option
       name,  the resource name, and the class name.  The option name begins with a hyphen and is
       all lowercase; it's used when creating widgets, and with the configure and cget commands.

       The resource and class names are used to initialize option default values by querying  the
       Tk  option  database.  The resource name is usually just the option name minus the hyphen,
       but may contain uppercase letters at word boundaries; the class name is usually  just  the
       resource  name with an initial capital, but not always.  For example, here are the option,
       resource, and class names for several text widget options:

                  -background         background         Background
                  -borderwidth        borderWidth        BorderWidth
                  -insertborderwidth  insertBorderWidth  BorderWidth
                  -padx               padX               Pad

       As is easily seen, sometimes the resource and class names can be inferred from the  option
       name, but not always.

       Snit  options  also have a resource name and a class name.  By default, these names follow
       the rule given above: the resource name is the option name without  the  hyphen,  and  the
       class  name  is the resource name with an initial capital.  This is true for both locally-
       defined options and explicitly delegated options:

                  snit::widget mywidget {
                      option -background
                      delegate option -borderwidth to hull
                      delegate option * to text
                # ...
                  }

       In this case, the widget class name is "Mywidget".  The widget has the following  options:
       -background,  which  is  locally defined, and -borderwidth, which is explicitly delegated;
       all other widgets are delegated to a component called "text", which is probably a Tk  text
       widget.  If so, mywidget has all the same options as a text widget.  The option, resource,
       and class names are as follows:

                  -background  background  Background
                  -borderwidth borderwidth Borderwidth
                  -padx        padX        Pad

       Note that the locally defined option, -background, happens to have the same three names as
       the  standard  Tk  -background option; and -pad, which is delegated implicitly to the text
       component, has the same three  names  for  mywidget  as  it  does  for  the  text  widget.
       -borderwidth,  on  the  other  hand,  has  different  resource and class names than usual,
       because the internal word "width" isn't capitalized.  For consistency, it should be;  this
       is done as follows:

                  snit::widget mywidget {
                option -background
                delegate option {-borderwidth borderWidth} to hull
                delegate option * to text
                # ...
                  }

       The class name will default to "BorderWidth", as expected.

       Suppose, however, that mywidget also delegated -padx and -pady to the hull.  In this case,
       both the resource name and the class name must be specified explicitly:

                  snit::widget mywidget {
                option -background
                delegate option {-borderwidth borderWidth} to hull
                delegate option {-padx padX Pad} to hull
                delegate option {-pady padY Pad} to hull
                delegate option * to text
                # ...
                  }

       Querying the option database: If you set your widgetclass and option  names  as  described
       above,  Snit  will  query  the  option  database  when  each instance is created, and will
       generally do the right thing when it comes to querying the option database.  The remainder
       of this section goes into the gory details.

       Initializing  locally  defined options: When an instance of a snit::widget is created, its
       locally defined options are initialized as follows: each option's resource and class names
       are  used  to query the Tk option database.  If the result is non-empty, it is used as the
       option's default; otherwise, the default hardcoded in the type  definition  is  used.   In
       either case, the default can be overridden by the caller.  For example,

                  option add *Mywidget.texture pebbled

                  snit::widget mywidget {
                option -texture smooth
                # ...
                  }

                  mywidget .mywidget -texture greasy

       Here,  -texture  would normally default to "smooth", but because of the entry added to the
       option database it defaults to "pebbled".  However, the caller has  explicitly  overridden
       the default, and so the new widget will be "greasy".

       Initializing  options  delegated to the hull: A snit::widget's hull is a widget, and given
       that its class has been set it is expected to query the option database for  itself.   The
       only  exception concerns options that are delegated to it with a different name.  Consider
       the following code:

                  option add *Mywidget.borderWidth 5
                  option add *Mywidget.relief sunken
                  option add *Mywidget.hullbackground red
                  option add *Mywidget.background green

                  snit::widget mywidget {
                delegate option -borderwidth to hull
                delegate option -hullbackground to hull as -background
                delegate option * to hull
                # ...
                  }

                  mywidget .mywidget

                  set A [.mywidget cget -relief]
                  set B [.mywidget cget -hullbackground]
                  set C [.mywidget cget -background]
                  set D [.mywidget cget -borderwidth]

       The question is, what are the values of variables A, B, C and D?

       The value of A is "sunken".  The hull is a Tk frame that has been given the  widget  class
       "Mywidget"; it will automatically query the option database and pick up this value.  Since
       the -relief option is implicitly delegated to the hull, Snit takes no action.

       The value of B is "red".  The hull will automatically pick up the value  "green"  for  its
       -background  option,  just  as  it  picked up the -relief value.  However, Snit knows that
       -hullbackground is mapped to the hull's -background option; hence, it queries  the  option
       database for -hullbackground and gets "red" and updates the hull accordingly.

       The  value  of  C  is also "red", because -background is implicitly delegated to the hull;
       thus, retrieving it is the same as retrieving -hullbackground.  Note  that  this  case  is
       unusual;  in  practice,  -background  would probably be explicitly delegated to some other
       component.

       The value of D is "5", but not for the reason you think.   Note  that  as  it  is  defined
       above,  the  resource  name for -borderwidth defaults to "borderwidth", whereas the option
       database entry is "borderWidth".  As with -relief, the hull picks up its own  -borderwidth
       option  before  Snit  does  anything.  Because the option is delegated under its own name,
       Snit assumes that the correct thing has happened, and doesn't worry about it any further.

       For snit::widgetadaptors, the case is somewhat altered.  Widget adaptors retain the widget
       class  of  their  hull,  and  the hull is not created automatically by Snit.  Instead, the
       snit::widgetadaptor must call installhull in its constructor.  The normal way to  do  this
       is as follows:

                  snit::widgetadaptor mywidget {
                # ...
                constructor {args} {
                    # ...
                    installhull using text -foreground white
                    #
                }
                #...
                  }

       In this case, the installhull command will create the hull using a command like this:

                  set hull [text $win -foreground white]

       The  hull  is  a  text  widget,  so its widget class is "Text".  Just as with snit::widget
       hulls, Snit assumes that it will pick up all of its normal  option  values  automatically;
       options  delegated  from  a different name are initialized from the option database in the
       same way.

       Initializing options delegated  to  other  components:  Non-hull  components  are  matched
       against  the  option  database  in  two  ways.  First, a component widget remains a widget
       still, and therefore is initialized from the option database in the  usual  way.   Second,
       the  option  database  is  queried  for  all  options  delegated to the component, and the
       component is initialized accordingly--provided that the install command is used to  create
       it.

       Before  option database support was added to Snit, the usual way to create a component was
       to simply create it in the constructor and  assign  its  command  name  to  the  component
       variable:

                  snit::widget mywidget {
                delegate option -background to myComp

                constructor {args} {
                    set myComp [text $win.text -foreground black]
                }
                  }

       The  drawback  of  this method is that Snit has no opportunity to initialize the component
       properly.  Hence, the following approach is now used:

                  snit::widget mywidget {
                delegate option -background to myComp

                constructor {args} {
                    install myComp using text $win.text -foreground black
                }
                  }

       The install command does the following:

       •      Builds a list of the options explicitly included in the install command -- in  this
              case, -foreground.

       •      Queries  the  option  database  for  all  options delegated explicitly to the named
              component.

       •      Creates the component using the specified command, after inserting into it  a  list
              of options and values read from the option database.  Thus, the explicitly included
              options (-foreground) will override anything read from the option database.

       •      If the widget definition  implicitly  delegated  options  to  the  component  using
              delegate  option  *, then Snit calls the newly created component's configure method
              to receive a list of all of the component's options.  From this Snit builds a  list
              of  options implicitly delegated to the component that were not explicitly included
              in the install command.  For all such options, Snit queries the option database and
              configures the component accordingly.

       Non-widget  components: The option database is never queried for snit::types, since it can
       only be queried given a Tk  widget  name.   However,  snit::widgets  can  have  non-widget
       components.   And if options are delegated to those components, and if the install command
       is used to install those components,  then  they  will  be  initialized  from  the  option
       database just as widget components are.

   MACROS AND META-PROGRAMMING
       The  snit::macro  command  enables a certain amount of meta-programming with Snit classes.
       For example, suppose you like to define properties: instance variables that  have  set/get
       methods.  Your code might look like this:

                  snit::type dog {
                      variable mood happy

                      method getmood {} {
                          return $mood
                      }

                      method setmood {newmood} {
                          set mood $newmood
                      }
                  }

       That's nine lines of text per property.  Or, you could define the following snit::macro:

                  snit::macro property {name initValue} {
                      variable $name $initValue

                      method get$name {} "return $name"

                      method set$name {value} "set $name \$value"
                  }

       Note that a snit::macro is just a normal Tcl proc defined in the slave interpreter used to
       compile type and widget definitions; as a result, it has access to all the  commands  used
       to define types and widgets.

       Given this new macro, you can define a property in one line of code:

                  snit::type dog {
                      property mood happy
                  }

       Within a macro, the commands variable and proc refer to the Snit type-definition commands,
       not the standard Tcl commands.  To get the standard Tcl commands, use _variable and _proc.

       Because a single slave interpreter is used for compiling all Snit types and widgets in the
       application,  there's  the  possibility  of  macro  name  collisions.  If you're writing a
       reuseable package using Snit, and you use some snit::macros, define them in  your  package
       namespace:

                  snit::macro mypkg::property {name initValue} { ... }

                  snit::type dog {
                      mypkg::property mood happy
                  }

       This leaves the global namespace open for application authors.

   VALIDATION TYPES
       A  validation  type  is  an object that can be used to validate Tcl values of a particular
       kind.  For example, snit::integer is used to validate that a Tcl value is an integer.

       Every validation type has a validate method which is  used  to  do  the  validation.  This
       method must take a single argument, the value to be validated; further, it must do nothing
       if the value is valid, but throw an error if the value is invalid:

                  snit::integer validate 5     ;# Does nothing
                  snit::integer validate 5.0   ;# Throws an error (not an integer!)

       The validate method will always return the validated  value  on  success,  and  throw  the
       -errorcode INVALID on error.

       Snit  defines  a family of validation types, all of which are implemented as snit::type's.
       They can be used as is; in addition, their instances serve as parameterized subtypes.  For
       example, a probability is a number between 0.0 and 1.0 inclusive:

                  snit::double probability -min 0.0 -max 1.0

       The  example  above  creates  an  instance  of  snit::double--a validation subtype--called
       probability, which can be used to validate probability values:

                  probability validate 0.5   ;# Does nothing
                  probability validate 7.9   ;# Throws an error

       Validation subtypes can be defined explicitly, as in the above example;  when  a  locally-
       defined option's -type is specified, they may also be created on the fly:

                  snit::enum ::dog::breed -values {mutt retriever sheepdog}

                  snit::type dog {
                      # Define subtypes on the fly...
                      option -breed -type {
                          snit::enum -values {mutt retriever sheepdog}
                      }

                      # Or use predefined subtypes...
                      option -breed -type ::dog::breed
                  }

       Any  object that has a validate method with the semantics described above can be used as a
       validation type; see Defining Validation Types for information on how to define new ones.

       Snit defines the following validation types:

       snit::boolean validate ?value?

       snit::boolean name
              Validates Tcl boolean values: 1, 0, on, off, yes, no, true, false.   It's  possible
              to  define subtypes--that is, instances--of snit::boolean, but as it has no options
              there's no reason to do so.

       snit::double validate ?value?

       snit::double name ?option value...?
              Validates floating-point values.   Subtypes  may  be  created  with  the  following
              options:

              -min min
                     Specifies  a  floating-point  minimum  bound;  a  value  is invalid if it is
                     strictly less than min.

              -max max
                     Specifies a floating-point maximum bound;  a  value  is  invalid  if  it  is
                     strictly greater than max.

       snit::enum validate ?value?

       snit::enum name ?option value...?
              Validates  that  a value comes from an enumerated list.  The base type is of little
              use by itself, as only subtypes  actually  have  an  enumerated  list  to  validate
              against.  Subtypes may be created with the following options:

              -values list
                     Specifies  a  list  of  valid  values.  A value is valid if and only if it's
                     included in the list.

       snit::fpixels validate ?value?

       snit::fpixels name ?option value...?
              Tk programs only. Validates screen distances, in any of the forms accepted by winfo
              fpixels. Subtypes may be created with the following options:

              -min min
                     Specifies  a  minimum  bound; a value is invalid if it is strictly less than
                     min.  The bound may be expressed in any  of  the  forms  accepted  by  winfo
                     fpixels.

              -max max
                     Specifies a maximum bound; a value is invalid if it is strictly greater than
                     max.  The bound may be expressed in any  of  the  forms  accepted  by  winfo
                     fpixels.

       snit::integer validate ?value?

       snit::integer name ?option value...?
              Validates integer values.  Subtypes may be created with the following options:

              -min min
                     Specifies  an  integer  minimum  bound; a value is invalid if it is strictly
                     less than min.

              -max max
                     Specifies an integer maximum bound; a value is invalid  if  it  is  strictly
                     greater than max.

       snit::listtype validate ?value?

       snit::listtype name ?option value...?
              Validates Tcl lists. Subtypes may be created with the following options:

              -minlen min
                     Specifies  a  minimum list length; the value is invalid if it has fewer than
                     min elements.  Defaults to 0.

              -maxlen max
                     Specifies a maximum list length; the value is invalid if it  more  than  max
                     elements.

              -type type
                     Specifies  the  type  of  the  list  elements;  type  must  be the name of a
                     validation type or subtype.  In the following example, the value of -numbers
                     must be a list of integers.

                         option -numbers -type {snit::listtype -type snit::integer}

                     Note  that  this  option doesn't support defining new validation subtypes on
                     the fly; that is, the following code will not work (yet, anyway):

                         option -numbers -type {
                             snit::listtype -type {snit::integer -min 5}
                         }

                     Instead, define the subtype explicitly:

                         snit::integer gt4 -min 5

                         snit::type mytype {
                             option -numbers -type {snit::listtype -type gt4}
                         }

       snit::pixels validate ?value?

       snit::pixels name ?option value...?
              Tk programs only. Validates screen distances, in any of the forms accepted by winfo
              pixels. Subtypes may be created with the following options:

              -min min
                     Specifies  a  minimum  bound; a value is invalid if it is strictly less than
                     min.  The bound may be expressed in any  of  the  forms  accepted  by  winfo
                     pixels.

              -max max
                     Specifies a maximum bound; a value is invalid if it is strictly greater than
                     max.  The bound may be expressed in any  of  the  forms  accepted  by  winfo
                     pixels.

       snit::stringtype validate ?value?

       snit::stringtype name ?option value...?
              Validates  Tcl  strings.  The  base type is of little use by itself, since very Tcl
              value is also a valid string.  Subtypes may be created with the following options:

              -minlen min
                     Specifies a minimum string length; the value is invalid if it has fewer than
                     min characters.  Defaults to 0.

              -maxlen max
                     Specifies  a maximum string length; the value is invalid if it has more than
                     max characters.

              -glob pattern
                     Specifies a string match pattern; the value is invalid if it  doesn't  match
                     the pattern.

              -regexp regexp
                     Specifies a regular expression; the value is invalid if it doesn't match the
                     regular expression.

              -nocase flag
                     By default, both -glob and -regexp matches are case-sensitive.   If  -nocase
                     is set to true, then both -glob and -regexp matches are case-insensitive.

       snit::window validate ?value?

       snit::window name
              Tk programs only.  Validates Tk window names.  The value must cause winfo exists to
              return  true;  otherwise,  the  value  is  invalid.   It's   possible   to   define
              subtypes--that  is, instances--of snit::window, but as it has no options at present
              there's no reason to do so.

   DEFINING VALIDATION TYPES
       There are three ways to define a new validation type:  as  a  subtype  of  one  of  Snit's
       validation  types,  as  a  validation  type command, and as a full-fledged validation type
       similar to those provided by Snit.   Defining  subtypes  of  Snit's  validation  types  is
       described above, under Validation Types.

       The  next simplest way to create a new validation type is as a validation type command.  A
       validation type is simply an object that has a validate method; the validate  method  must
       take  one  argument,  a  value,  return  the value if it is valid, and throw an error with
       -errorcode INVALID if the value is invalid.  This can be done with  a  simple  proc.   For
       example, the snit::boolean validate type could have been implemented like this:

                  proc ::snit::boolean {"validate" value} {
                      if {![string is boolean -strict $value]} {
                          return -code error -errorcode INVALID  "invalid boolean \"$value\", should be one of: 1, 0, ..."
                      }

                      return $value
                  }

       A  validation  type  defined  in  this  way  cannot  be  subtyped, of course; but for many
       applications this will be sufficient.

       Finally, one can define a full-fledged, subtype-able  validation  type  as  a  snit::type.
       Here's a skeleton to get you started:

                  snit::type myinteger {
                      # First, define any options you'd like to use to define
                      # subtypes.  Give them defaults such that they won't take
                      # effect if they aren't used, and marked them "read-only".
                      # After all, you shouldn't be changing their values after
                      # a subtype is defined.
                      #
                      # For example:

                      option -min -default "" -readonly 1
                      option -max -default "" -readonly 1

                      # Next, define a "validate" type method which should do the
                      # validation in the basic case.  This will allow the
                      # type command to be used as a validation type.

                      typemethod validate {value} {
                          if {![string is integer -strict $value]} {
                              return -code error -errorcode INVALID  "invalid value \"$value\", expected integer"
                          }

                          return $value
                      }

                      # Next, the constructor should validate the subtype options,
                      # if any.  Since they are all readonly, we don't need to worry
                      # about validating the options on change.

                      constructor {args} {
                          # FIRST, get the options
                          $self configurelist $args

                          # NEXT, validate them.

                          # I'll leave this to your imagination.
                      }

                      # Next, define a "validate" instance method; its job is to
                      # validate values for subtypes.

                      method validate {value} {
                          # First, call the type method to do the basic validation.
                          $type validate $value

                          # Now we know it's a valid integer.

                          if {("" != $options(-min) && $value < $options(-min))  ||
                              ("" != $options(-max) && $value > $options(-max))} {
                              # It's out of range; format a detailed message about
                              # the error, and throw it.

                              set msg "...."

                              return -code error -errorcode INVALID $msg
                          }

                          # Otherwise, if it's valid just return it.
                          return $valid
                      }
                  }

       And now you have a type that can be subtyped.

       The  file  "validate.tcl" in the Snit distribution defines all of Snit's validation types;
       you can find the complete implementation for snit::integer and the other types  there,  to
       use as examples for your own types.

CAVEATS

       If you have problems, find bugs, or new ideas you are hereby cordially invited to submit a
       report of your problem, bug, or idea as explained in the  section  Bugs,  Ideas,  Feedback
       below.

       Additionally,    you    might    wish    to    join    the    Snit   mailing   list;   see
       http://www.wjduquette.com/snit for details.

       One particular area to watch is using snit::widgetadaptor to adapt megawidgets created  by
       other  megawidget  packages;  correct  widget  destruction  depends  on  the  order of the
       <Destroy> bindings.  The wisest course is simply not to do this.

KNOWN BUGS

       •      Error stack traces returned by Snit 1.x are extremely ugly  and  typically  contain
              far  too  much  information  about  Snit  internals.   The  error messages are much
              improved in Snit 2.2.

       •      Also see the Project Trackers as explained in the  section  Bugs,  Ideas,  Feedback
              below.

HISTORY

       During the course of developing Notebook (See http://www.wjduquette.com/notebook), my Tcl-
       based personal notebook application, I found I was writing it as a collection of  objects.
       I  wasn't  using  any  particular object-oriented framework; I was just writing objects in
       pure  Tcl   following   the   guidelines   in   my   Guide   to   Object   Commands   (see
       http://www.wjduquette.com/tcl/objects.html),  along  with a few other tricks I'd picked up
       since.  And though it was working well, it quickly became tiresome because of  the  amount
       of boilerplate code associated with each new object type.

       So  that  was one thing--tedium is a powerful motivator.  But the other thing I noticed is
       that I wasn't using inheritance at all, and I wasn't missing it.   Instead,  I  was  using
       delegation: objects that created other objects and delegated methods to them.

       And  I  said to myself, "This is getting tedious...there has got to be a better way."  And
       one afternoon, on a whim, I started working on Snit, an object system that works  the  way
       Tcl  works.   Snit doesn't support inheritance, but it's great at delegation, and it makes
       creating megawidgets easy.

       If you have any comments or suggestions (or bug reports!) don't hesitate to send me e-mail
       at  will@wjduquette.com.   In addition, there's a Snit mailing list; you can find out more
       about it at the Snit home page (see http://www.wjduquette.com/snit).

CREDITS

       Snit has been designed and implemented from the very beginning  by  William  H.  Duquette.
       However,  much credit belongs to the following people for using Snit and providing me with
       valuable feedback:  Rolf  Ade,  Colin  McCormack,  Jose  Nazario,  Jeff  Godfrey,  Maurice
       Diamanti,  Egon  Pasztor, David S. Cargo, Tom Krehbiel, Michael Cleverly, Andreas Kupries,
       Marty Backe, Andy Goth, Jeff Hobbs, Brian Griffin, Donal Fellows,  Miguel  Sofer,  Kenneth
       Green,  and Anton Kovalenko.  If I've forgotten anyone, my apologies; let me know and I'll
       add your name to the list.

BUGS, IDEAS, FEEDBACK

       This document, and the package it describes,  will  undoubtedly  contain  bugs  and  other
       problems.    Please   report   such   in   the   category  snit  of  the  Tcllib  Trackers
       [http://core.tcl.tk/tcllib/reportlist].  Please also report any ideas for enhancements you
       may have for either package and/or documentation.

       When proposing code changes, please provide unified diffs, i.e the output of diff -u.

       Note further that attachments are strongly preferred over inlined patches. Attachments can
       be made by going to the Edit form of the ticket immediately after its creation,  and  then
       using the left-most button in the secondary navigation bar.

KEYWORDS

       BWidget, C++, Incr Tcl, Snit, adaptors, class, mega widget, object, object oriented, type,
       widget, widget adaptors

CATEGORY

       Programming tools

COPYRIGHT

       Copyright (c) 2003-2009, by William H. Duquette