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

NAME

       snitfaq - Snit Frequently Asked Questions

DESCRIPTION

OVERVIEW

   WHAT IS THIS DOCUMENT?
       This  is an atypical FAQ list, in that few of the questions are frequently asked.  Rather,
       these are the questions I think a newcomer to Snit should be asking.  This file is  not  a
       complete reference to Snit, however; that information is in the snit man page.

   WHAT IS SNIT?
       Snit  is  a  framework  for defining abstract data types and megawidgets in pure Tcl.  The
       name "Snit" stands for "Snit's Not Incr Tcl",  signifying  that  Snit  takes  a  different
       approach  to defining objects than does Incr Tcl, the best known object framework for Tcl.
       Had I realized that Snit would become at all popular, I'd probably have  chosen  something
       else.

       The primary purpose of Snit is to be object glue--to help you compose diverse objects from
       diverse sources into types and megawidgets with clean, convenient interfaces so  that  you
       can more easily build your application.

       Snit  isn't  about  theoretical  purity  or minimalist design; it's about being able to do
       powerful things easily and consistently without having to think about  them--so  that  you
       can concentrate on building your application.

       Snit   isn't   about   implementing  thousands  of  nearly  identical  carefully-specified
       lightweight thingamajigs--not as individual Snit objects.  Traditional Tcl methods will be
       much  faster,  and  not  much  more  complicated.   But Snit is about implementing a clean
       interface to manage a collection of  thousands  of  nearly  identical  carefully-specified
       lightweight  thingamajigs  (e.g.,  think  of  the text widget and text tags, or the canvas
       widget and canvas objects).  Snit lets you hide the details of just how those thingamajigs
       are stored--so that you can ignore it, and concentrate on building your application.

       Snit  isn't  a  way of life, a silver bullet, or the Fountain of Youth. It's just a way of
       managing complexity--and of managing some of the  complexity  of  managing  complexity--so
       that you can concentrate on building your application.

   WHAT VERSION OF TCL DOES SNIT REQUIRE?
       Snit 1.3 requires Tcl 8.3 or later; Snit 2.2 requires Tcl 8.5 or later.  See SNIT VERSIONS
       for the differences between Snit 1.3 and Snit 2.2.

   WHERE CAN I DOWNLOAD SNIT?
       Snit is part of Tcllib, the standard Tcl library, so you might already have it.  It's also
       available at the Snit Home Page, http://www.wjduquette.com/snit.

   WHAT ARE SNIT'S GOALS?
       •      A  Snit  object  should  be  at  least as efficient as a hand-coded Tcl object (see
              http://www.wjduquette.com/tcl/objects.html).

       •      The fact that Snit was used in an object's  implementation  should  be  transparent
              (and irrelevant) to clients of that object.

       •      Snit  should  be  able  to  encapsulate objects from other sources, particularly Tk
              widgets.

       •      Snit megawidgets should be (to the extent possible) indistinguishable in  interface
              from Tk widgets.

       •      Snit  should  be  Tclish--that is, rather than trying to emulate C++, Smalltalk, or
              anything else, it should try to emulate Tcl itself.

       •      It should have a simple, easy-to-use, easy-to-remember syntax.

   HOW IS SNIT DIFFERENT FROM OTHER OO FRAMEWORKS?
       Snit is unique among Tcl object systems in that it is based  not  on  inheritance  but  on
       delegation.   Object  systems  based on inheritance only allow you to inherit from classes
       defined using the same system, and that's a shame.  In Tcl, an  object  is  anything  that
       acts  like an object; it shouldn't matter how the object was implemented.  I designed Snit
       to help me 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.

       Note that you can achieve the effect of inheritance using COMPONENTS  and  DELEGATION--and
       you can inherit from anything that looks like a Tcl object.

   WHAT CAN I DO WITH SNIT?
       Using Snit, a programmer can:

       •      Create abstract data types and Tk megawidgets.

       •      Define instance variables, type variables, and Tk-style options.

       •      Define constructors, destructors, instance methods, type methods, procs.

       •      Assemble  a  type  out  of  component  types.   Instance methods and options can be
              delegated to the component types automatically.

SNIT VERSIONS

   WHICH VERSION OF SNIT SHOULD I USE?
       The current Snit distribution includes two versions, Snit 1.3 and Snit  2.2.   The  reason
       that both are included is that Snit 2.2 takes advantage of a number of new features of Tcl
       8.5 to improve run-time efficiency;  as  a  side-effect,  the  ugliness  of  Snit's  error
       messages  and  stack traces has been reduced considerably.  The cost of using Snit 2.2, of
       course, is that you must target Tcl 8.5.

       Snit 1.3, on the other hand, lacks Snit 2.2's optimizations, but requires only Tcl 8.3 and
       later.

       In  short, if you're targetting Tcl 8.3 or 8.4 you should use Snit 1.3.  If you can afford
       to target Tcl 8.5, you should definitely use Snit 2.2.  If you will  be  targetting  both,
       you  can  use  Snit  1.3  exclusively,  or  (if  your  code  is  unaffected  by  the minor
       incompatibilities between the two versions) you can use Snit 1.3 for Tcl 8.4 and Snit  2.2
       for Tcl 8.5.

   HOW DO I SELECT THE VERSION OF SNIT I WANT TO USE?
       To always use Snit 1.3 (or a later version of Snit 1.x), invoke Snit as follows:

              package require snit 1.3

       To always use Snit 2.2 (or a later version of Snit 2.x), say this instead:

              package require snit 2.2

       Note  that  if  you  request Snit 2.2 explicitly, your application will halt with Tcl 8.4,
       since Snit 2.2 is unavailable for Tcl 8.4.

       If you wish your application to always use the latest available  version  of  Snit,  don't
       specify a version number:

              package require snit

       Tcl  will find and load the latest version that's available relative to the version of Tcl
       being used.  In this case, be careful to avoid using any incompatible features.

   HOW ARE SNIT 1.3 AND SNIT 2.2 INCOMPATIBLE?
       To the extent possible, Snit 2.2 is intended to be a drop-in  replacement  for  Snit  1.3.
       Unfortunately,  some incompatibilities were inevitable because Snit 2.2 uses Tcl 8.5's new
       namespace ensemble mechanism to implement subcommand  dispatch.   This  approach  is  much
       faster  than  the  mechanism  used  in  Snit  1.3,  and  also results in much better error
       messages; however, it also places new constraints on the implementation.

       There are four specific incompatibilities between Snit 1.3 and Snit 2.2.

       •      Snit 1.3 supports implicit naming of objects.  Suppose you define a new  snit::type
              called dog.  You can create instances of dog in three ways:

              dog spot               ;# Explicit naming
              set obj1 [dog %AUTO%]  ;# Automatic naming
              set obj2 [dog]         ;# Implicit naming

              In  Snit 2.2, type commands are defined using the namespace ensemble mechanism; and
              namespace ensemble doesn't allow  an  ensemble  command  to  be  called  without  a
              subcommand.   In short, using namespace ensemble there's no way to support implicit
              naming.

              All is not lost, however.  If the type has no type methods, then the  type  command
              is  a  simple  command rather than an ensemble, and namespace ensemble is not used.
              In this case, implicit naming is still possible.

              In short, you can have implicit naming if you're willing to do without type methods
              (including  the  standard  type  methods,  like  $type  info).   To  do so, use the
              -hastypemethods pragma:

              pragma -hastypemethods 0

       •      Hierarchical methods and type methods are implemented differently in Snit 2.2.

              A  hierarchical  method  is  an  instance  method  which  has  subcommands;   these
              subcommands  are  themselves  methods.   The  Tk  text widget's tag command and its
              subcommands  are  examples  of  hierarchical  methods.   You  can  implement   such
              subcommands in Snit simply by including multiple words in the method names:

              method {tag configure} {tag args} { ... }

              method {tag cget} {tag option} {...}

              Here we've implicitly defined a tag method which has two subcommands, configure and
              cget.

              In Snit 1.3, hierarchical methods could be called in two ways:

              $obj tag cget -myoption      ;# The good way
              $obj {tag cget} -myoption    ;# The weird way

              In the second call, we see that a hierarchical method or type method is simply  one
              whose name contains multiple words.

              In Snit 2.2 this is no longer the case, and the "weird" way of calling hierarchical
              methods and type methods no longer works.

       •      The third incompatibility derives from  the  second.   In  Snit  1.3,  hierarchical
              methods  were also simply methods whose name contains multiple words.  As a result,
              $obj info methods returned the full names of  all  hierarchical  methods.   In  the
              example  above,  the list returned by $obj info methods would include tag configure
              and tag cget but not tag, since tag is defined only implicitly.

              In Snit 2.2, hierarchical methods and type methods are no longer simply ones  whose
              name  contains multiple words; in the above example, the list returned by $obj info
              methods would include tag but not tag configure or tag cget.

       •      The fourth incompatibility is due  to  a  new  feature.   Snit  2.2  uses  the  new
              namespace  path  command  so that a type's code can call any command defined in the
              type's parent namespace without qualification or importation.  For example, suppose
              you  have a package called mypackage which defines a number of commands including a
              type, ::mypackage::mytype.  Thanks to namespace path, the type's code can call  any
              of the other commands defined in ::mypackage::.

              This  is extremely convenient.  However, it also means that commands defined in the
              parent namespace, ::mypackage:: can block the type's access  to  identically  named
              commands  in  the  global  namespace.   This can lead to bugs.  For example, Tcllib
              includes a type called ::tie::std::file.  This type's code calls the standard  file
              command.    When   run  with  Snit  2.2,  the  code  broke--  the  type's  command,
              ::tie::std::file, is itself a command  in  the  type's  parent  namespace,  and  so
              instead of calling the standard file command, the type found itself calling itself.

   ARE THERE OTHER DIFFERENCES BETWEEN SNIT 1.X AND SNIT 2.2?
       Yes.

       •      Method dispatch is considerably faster.

       •      Many error messages and stack traces are cleaner.

       •      The  -simpledispatch  pragma  is  obsolete,  and  ignored  if present. In Snit 1.x,
              -simpledispatch substitutes a faster mechanism for method dispatch, at the cost  of
              losing certain features.  Snit 2.2 method dispatch is faster still in all cases, so
              -simpledispatch is no longer needed.

       •      In Snit 2.2, a type's code (methods, type methods, etc.) can call commands from the
              type's   parent   namespace  without  qualifying  or  importing  them,  i.e.,  type
              ::parentns::mytype's code can call ::parentns::someproc as just someproc.

              This is extremely useful when a type is defined as part of a  larger  package,  and
              shares  a parent namespace with the rest of the package; it means that the type can
              call other commands defined by the package without any extra work.

              This feature depends on the new Tcl 8.5 namespace path command,  which  is  why  it
              hasn't  been  implemented  for  V1.x.   V1.x  code can achieve something similar by
              placing

              namespace import [namespace parent]::*

              in a type constructor.  This is less useful, however, as it  picks  up  only  those
              commands  which  have already been exported by the parent namespace at the time the
              type is defined.

OBJECTS

   WHAT IS AN OBJECT?
       A full description of object-oriented  programming  is  beyond  the  scope  of  this  FAQ,
       obviously.  In simple terms, an object is an instance of an abstract data type--a coherent
       bundle of code and data.  There are many ways to represent objects  in  Tcl/Tk;  the  best
       known examples are the Tk widgets.

       A  Tk  widget  is an object; it is represented by a Tcl command.  The object's methods are
       subcommands of the Tcl command.  The object's properties are options  accessed  using  the
       configure and cget methods.  Snit uses the same conventions as Tk widgets do.

   WHAT IS AN ABSTRACT DATA TYPE?
       In  computer science terms, an abstract data type is a complex data structure along with a
       set of operations--a stack, a queue, a binary tree, etc--that is to say, in modern  terms,
       an  object.   In  systems  that include some form of inheritance the word class is usually
       used instead of abstract data type, but as Snit  doesn't  implement  inheritance  as  it's
       ordinarily  understood  the  older  term seems more appropriate.  Sometimes this is called
       object-based programming as opposed to object-oriented programming.   Note  that  you  can
       easily create the effect of inheritance using COMPONENTS and DELEGATION.

       In  Snit,  as in Tk, a type is a command that creates instances -- objects -- which belong
       to the type.  Most types define some number of options which can be set at creation  time,
       and usually can be changed later.

       Further,  an instance is also a Tcl command--a command that gives access to the operations
       which are defined for that abstract data type.  Conventionally, the operations are defined
       as  subcommands  of  the  instance  command.   For  example, to insert text into a Tk text
       widget, you use the text widget's insert subcommand:

                  # Create a text widget and insert some text in it.
                  text .mytext -width 80 -height 24
                  .mytext insert end "Howdy!"

       In this example, text is the type command and .mytext is the instance command.

       In Snit, object subcommands are generally called INSTANCE METHODS.

   WHAT KINDS OF ABSTRACT DATA TYPES DOES SNIT PROVIDE?
       Snit allows you to define three kinds of abstract data type:

       •      snit::typesnit::widgetsnit::widgetadaptor

   WHAT IS A SNIT::TYPE?
       A snit::type is a non-GUI abstract data type, e.g., a stack or a queue.   snit::types  are
       defined  using  the  snit::type  command.   For  example,  if  you were designing a kennel
       management system for a dog breeder, you'd need a dog type.

              % snit::type dog {
                  # ...
              }
              ::dog
              %

       This definition defines a new command (::dog, in this case) that can be used to define dog
       objects.

       An  instance  of  a snit::type can have INSTANCE METHODS, INSTANCE VARIABLES, OPTIONS, and
       COMPONENTS.  The type itself can have TYPE METHODS, TYPE VARIABLES, TYPE  COMPONENTS,  and
       PROCS.

   WHAT IS A SNIT::WIDGET?, THE SHORT STORY
       A  snit::widget  is  a Tk megawidget built using Snit; it is very similar to a snit::type.
       See WIDGETS.

   WHAT IS A SNIT::WIDGETADAPTOR?, THE SHORT STORY
       A snit::widgetadaptor uses Snit to wrap an  existing  widget  type  (e.g.,  a  Tk  label),
       modifying  its  interface  to  a  lesser  or  greater  extent.   It  is  very similar to a
       snit::widget.  See WIDGET ADAPTORS.

   HOW DO I CREATE AN INSTANCE OF A SNIT::TYPE?
       You create an instance of a snit::type by passing the new instance's name  to  the  type's
       create method.  In the following example, we create a dog object called spot.

              % snit::type dog {
                  # ....
              }
              ::dog
              % dog create spot
              ::spot
              %

       In  general,  the  create  method name can be omitted so long as the instance name doesn't
       conflict with any defined TYPE METHODS. (See TYPE COMPONENTS for the special case in which
       this doesn't work.)  So the following example is identical to the previous example:

              % snit::type dog {
                  # ....
              }
              ::dog
              % dog spot
              ::spot
              %

       This document generally uses the shorter form.

       If the dog type defines OPTIONS, these can usually be given defaults at creation time:

              % snit::type dog {
                  option -breed mongrel
                  option -color brown

                  method bark {} { return "$self barks." }
              }
              ::dog
              % dog create spot -breed dalmation -color spotted
              ::spot
              % spot cget -breed
              dalmation
              % spot cget -color
              spotted
              %

       Once created, the instance name now names a new Tcl command that is used to manipulate the
       object.  For example, the following code makes the dog bark:

              % spot bark
              ::spot barks.
              %

   HOW DO I REFER TO AN OBJECT INDIRECTLY?
       Some programmers prefer to save the object name in a variable, and reference it that  way.
       For example,

              % snit::type dog { ... }
              ::dog
              % set d [dog spot -breed dalmation -color spotted]
              ::spot
              % $d cget -breed
              dalmation
              % $d bark
              ::spot barks.
              %

       If  you  prefer  this  style,  you  might prefer to have Snit generate the instance's name
       automatically.

   HOW CAN I GENERATE THE OBJECT NAME AUTOMATICALLY?
       If you'd like Snit to generate an object name for you,  use  the  %AUTO%  keyword  as  the
       requested name:

              % snit::type dog { ... }
              ::dog
              % set d [dog %AUTO%]
              ::dog2
              % $d bark
              ::dog2 barks.
              %

       The %AUTO% keyword can be embedded in a longer string:

              % set d [dog obj_%AUTO%]
              ::obj_dog4
              % $d bark
              ::obj_dog4 barks.
              %

   CAN TYPES BE RENAMED?
       Tcl's  rename command renames other commands.  It's a common technique in Tcl to modify an
       existing command by renaming it and defining a new command with the original name; the new
       command usually calls the renamed command.

       snit::type  commands,  however,  should  never  be renamed; to do so breaks the connection
       between the type and its objects.

   CAN OBJECTS BE RENAMED?
       Tcl's rename command renames other commands.  It's a common technique in Tcl to modify  an
       existing command by renaming it and defining a new command with the original name; the new
       command usually calls the renamed command.

       All Snit objects (including widgets  and  widgetadaptors)  can  be  renamed,  though  this
       flexibility has some consequences:

       •      In  an instance method, the implicit argument self will always contain the object's
              current name, so instance methods can always  call  other  instance  methods  using
              $self.

       •      If  the  object  is  renamed,  however, then $self's value will change.  Therefore,
              don't use $self for anything that will break if $self changes. For  example,  don't
              pass a callback command to another object like this:

                  .btn configure -command [list $self ButtonPress]

              You'll get an error if .btn calls your command after your object is renamed.

       •      Instead, your object should define its callback command like this:

                  .btn configure -command [mymethod ButtonPress]

              The  mymethod  command  returns  code that will call the desired method safely; the
              caller of the callback can add additional arguments to the end of  the  command  as
              usual.

       •      Every  object  has  a private namespace; the name of this namespace is available in
              method bodies, etc., as the value of the implicit argument selfns.  This  value  is
              constant  for  the  life of the object.  Use $selfns instead of $self if you need a
              unique token to identify the object.

       •      When a snit::widget's instance command is renamed, its Tk window name  remains  the
              same  --  and  is  still  extremely  important. Consequently, the Tk window name is
              available in method bodies as the value of the implicit argument win.   This  value
              is  constant for the life of the object.  When creating child windows, it's best to
              use $win.child rather than $self.child as the name of the child window.

   HOW DO I DESTROY A SNIT OBJECT?
       Any Snit object of any type can be destroyed by renaming it to the empty string using  the
       Tcl rename command.

       Snit  megawidgets  (i.e.,  instances  of  snit::widget  and  snit::widgetadaptor)  can  be
       destroyed like any other widget: by using the Tk destroy command on the widget or  on  one
       of its ancestors in the window hierarchy.

       Every instance of a snit::type has a destroy method:

              % snit::type dog { ... }
              ::dog
              % dog spot
              ::spot
              % spot bark
              ::spot barks.
              % spot destroy
              % spot barks
              invalid command name "spot"
              %

       Finally,  every  Snit  type has a type method called destroy; calling it destroys the type
       and all of its instances:

              % snit::type dog { ... }
              ::dog
              % dog spot
              ::spot
              % spot bark
              ::spot barks.
              % dog destroy
              % spot bark
              invalid command name "spot"
              % dog fido
              invalid command name "dog"
              %

INSTANCE METHODS

   WHAT IS AN INSTANCE METHOD?
       An instance method is a procedure associated with  a  specific  object  and  called  as  a
       subcommand  of  the object's command.  It is given free access to all of the object's type
       variables, instance variables, and so forth.

   HOW DO I DEFINE AN INSTANCE METHOD?
       Instance methods are defined in the type definition using the method statement.   Consider
       the following code that might be used to add dogs to a computer simulation:

              % snit::type dog {
                  method bark {} {
                      return "$self barks."
                  }

                  method chase {thing} {
                      return "$self chases $thing."
                  }
              }
              ::dog
              %

       A dog can bark, and it can chase things.

       The  method  statement  looks  just  like  a  normal Tcl proc, except that it appears in a
       snit::type definition.  Notice that every instance method gets an implicit argument called
       self;  this  argument  contains  the  object's  name.   (There's  more  on implicit method
       arguments below.)

   HOW DOES A CLIENT CALL AN INSTANCE METHOD?
       The method name becomes a subcommand of the object.  For example, let's  put  a  simulated
       dog through its paces:

              % dog spot
              ::spot
              % spot bark
              ::spot barks.
              % spot chase cat
              ::spot chases cat.
              %

   HOW DOES AN INSTANCE METHOD CALL ANOTHER INSTANCE METHOD?
       If  method  A needs to call method B on the same object, it does so just as a client does:
       it calls method B as a subcommand of the object itself, using the object  name  stored  in
       the implicit argument self.

       Suppose, for example, that our dogs never chase anything without barking at them:

              % snit::type dog {
                  method bark {} {
                      return "$self barks."
                  }

                  method chase {thing} {
                      return "$self chases $thing.  [$self bark]"
                  }
              }
              ::dog
              % dog spot
              ::spot
              % spot bark
              ::spot barks.
              % spot chase cat
              ::spot chases cat.  ::spot barks.
              %

   ARE THERE ANY LIMITATIONS ON INSTANCE METHOD NAMES?
       Not  really,  so  long  as  you  avoid  the  standard  instance  method  names: configure,
       configurelist, cget, destroy, and info.  Also, method names consisting of  multiple  words
       define hierarchical methods.

   WHAT IS A HIERARCHICAL METHOD?
       An  object's  methods  are  subcommands  of  the  object's instance command.  Hierarchical
       methods allow an object's methods to have subcommands of their own; and these can in  turn
       have  subcommands,  and so on.  This allows the programmer to define a tree-shaped command
       structure, such as is used by many of the Tk  widgets--the  subcommands  of  the  Tk  text
       widget's tag method are hierarchical methods.

   HOW DO I DEFINE A HIERARCHICAL METHOD?
       Define  methods  whose  names consist of multiple words.  These words define the hierarchy
       implicitly.  For example, the following code defines a tag method  with  subcommands  cget
       and configure:

              snit::widget mytext {
                  method {tag configure} {tag args} { ... }

                  method {tag cget} {tag option} {...}
              }

       Note  that  there  is  no  explicit  definition  for the tag method; it is implicit in the
       definition of tag configure and tag cget.  If you tried to define tag explicitly  in  this
       example, you'd get an error.

   HOW DO I CALL HIERARCHICAL METHODS?
       As subcommands of subcommands.

              % mytext .text
              .text
              % .text tag configure redtext -foreground red -background black
              % .text tag cget redtext -foreground
              red
              %

   HOW DO I MAKE AN INSTANCE METHOD PRIVATE?
       It's  often  useful  to  define  private methods, that is, instance methods intended to be
       called only by other methods of the same object.

       Snit doesn't implement any access control on instance methods, so all methods are de facto
       public.   Conventionally,  though,  the  names  of  public methods begin with a lower-case
       letter, and the names of private methods begin with an upper-case letter.

       For example, suppose our simulated dogs only bark in response to other stimuli; they never
       bark just for fun.  So the bark method becomes Bark to indicate that it is private:

              % snit::type dog {
                  # Private by convention: begins with uppercase letter.
                  method Bark {} {
                      return "$self barks."
                  }

                  method chase {thing} {
                      return "$self chases $thing. [$self Bark]"
                  }
              }
              ::dog
              % dog fido
              ::fido
              % fido chase cat
              ::fido chases cat. ::fido barks.
              %

   ARE THERE ANY LIMITATIONS ON INSTANCE METHOD ARGUMENTS?
       Method argument lists are defined just like normal Tcl proc argument lists; in particular,
       they can include arguments with default values and the args argument.

       However, every method also has a number of implicit arguments provided by Snit in addition
       to  those  explicitly defined.  The names of these implicit arguments may not used to name
       explicit arguments.

   WHAT IMPLICIT ARGUMENTS ARE PASSED TO EACH INSTANCE METHOD?
       The arguments implicitly passed to every method are type, selfns, win, and self.

   WHAT IS $TYPE?
       The implicit argument type contains the fully qualified name of the object's type:

              % snit::type thing {
                  method mytype {} {
                      return $type
                  }
              }
              ::thing
              % thing something
              ::something
              % something mytype
              ::thing
              %

   WHAT IS $SELF?
       The implicit argument self contains the object's fully qualified name.

       If the object's command is renamed, then $self will change to match in  subsequent  calls.
       Thus, your code should not assume that $self is constant unless you know for sure that the
       object will never be renamed.

              % snit::type thing {
                  method myself {} {
                      return $self
                  }
              }
              ::thing
              % thing mutt
              ::mutt
              % mutt myself
              ::mutt
              % rename mutt jeff
              % jeff myself
              ::jeff
              %

   WHAT IS $SELFNS?
       Each Snit object has a private namespace in which to  store  its  INSTANCE  VARIABLES  and
       OPTIONS.   The  implicit  argument  selfns  contains the name of this namespace; its value
       never changes, and is constant for the life of the  object,  even  if  the  object's  name
       changes:

              % snit::type thing {
                  method myNameSpace {} {
                      return $selfns
                  }
              }
              ::thing
              % thing jeff
              ::jeff
              % jeff myNameSpace
              ::thing::Snit_inst3
              % rename jeff mutt
              % mutt myNameSpace
              ::thing::Snit_inst3
              %

       The  above  example  reveals  how Snit names an instance's private namespace; however, you
       should not write code that depends on the specific naming convention, as it  might  change
       in future releases.

   WHAT IS $WIN?
       The  implicit  argument  win is defined for all Snit methods, though it really makes sense
       only for those of WIDGETS and WIDGET ADAPTORS.  $win is simply the original  name  of  the
       object,  whether  it's  been  renamed  or not.  For widgets and widgetadaptors, it is also
       therefore the name of a Tk window.

       When a snit::widgetadaptor is used to modify the interface of a widget or  megawidget,  it
       must rename the widget's original command and replace it with its own.

       Thus,  using  win  whenever  the Tk window name is called for means that a snit::widget or
       snit::widgetadaptor can be  adapted  by  a  snit::widgetadaptor.   See  WIDGETS  for  more
       information.

   HOW DO I PASS AN INSTANCE METHOD AS A CALLBACK?
       It depends on the context.

       Suppose  in  my application I have a dog object named fido, and I want fido to bark when a
       Tk button called .bark is pressed.  In this case, I create the  callback  command  in  the
       usual way, using list:

                  button .bark -text "Bark!" -command [list fido bark]

       In  typical Tcl style, we use a callback to hook two independent components together.  But
       suppose that the dog object has a graphical interface and owns the button itself?  In this
       case,  the  dog  must  pass  one  of  its own instance methods to the button it owns.  The
       obvious thing to do is this:

              % snit::widget dog {
                  constructor {args} {
                      #...
                      button $win.barkbtn -text "Bark!" -command [list $self bark]
                      #...
                  }
              }
              ::dog
              %

       (Note that in this example, our dog becomes a snit::widget, because it has  GUI  behavior.
       See  WIDGETS for more.)  Thus, if we create a dog called .spot, it will create a Tk button
       called .spot.barkbtn; when pressed, the button will call $self bark.

       Now, this will work--provided that .spot is never renamed to something else.   But  surely
       renaming  widgets  is  abnormal?   And  so  it is--unless .spot is the hull component of a
       snit::widgetadaptor.  If it is, then it will be renamed, and .spot will become the name of
       the  snit::widgetadaptor  object.  When the button is pressed, the command $self bark will
       be handled by the snit::widgetadaptor, which might or might not do the right thing.

       There's a safer way to do it, and it looks like this:

              % snit::widget dog {
                  constructor {args} {
                      #...
                      button $win.barkbtn -text "Bark!" -command [mymethod bark]
                      #...
                  }
              }
              ::dog
              %

       The command mymethod takes any number of arguments, and can be used like list to build  up
       a  callback  command;  the  only difference is that mymethod returns a form of the command
       that won't change even if the instance's name changes.

       On the other hand, you might prefer to allow a widgetadaptor to  override  a  method  such
       that your renamed widget will call the widgetadaptor's method instead of its own.  In this
       case, using [list $self bark] will do what you want...but this is a technique which should
       be used only in carefully controlled circumstances.

   HOW DO I DELEGATE INSTANCE METHODS TO A COMPONENT?
       See DELEGATION.

INSTANCE VARIABLES

   WHAT IS AN INSTANCE VARIABLE?
       An  instance  variable  is a private variable associated with some particular Snit object.
       Instance variables can be scalars or arrays.

   HOW IS A SCALAR INSTANCE VARIABLE DEFINED?
       Scalar instance variables are defined in the type definition using the variable statement.
       You can simply name it, or you can initialize it with a value:

              snit::type mytype {
                  # Define variable "greeting" and initialize it with "Howdy!"
                  variable greeting "Howdy!"
              }

   HOW IS AN ARRAY INSTANCE VARIABLE DEFINED?
       Array  instance  variables  are  also  defined  in  the type definition using the variable
       command.  You can initialize them at the same time by specifying the -array option:

              snit::type mytype {
                  # Define array variable "greetings"
                  variable greetings -array {
                      formal "Good Evening"
                      casual "Howdy!"
                  }
              }

   WHAT HAPPENS IF I DON'T INITIALIZE AN INSTANCE VARIABLE?
       Variables do not really exist until they are given values.  If you  do  not  initialize  a
       variable  when  you  define  it,  then  you  must  be sure to assign a value to it (in the
       constructor, say, or in some method) before you reference it.

   ARE THERE ANY LIMITATIONS ON INSTANCE VARIABLE NAMES?
       Just a few.

       First, every Snit object has a built-in instance variable  called  options,  which  should
       never be redefined.

       Second, all names beginning with "Snit_" are reserved for use by Snit internal code.

       Third, instance variable names containing the namespace delimiter (::) are likely to cause
       great confusion.

   DO I NEED TO DECLARE MY INSTANCE VARIABLES IN MY METHODS?
       No. Once you've defined an instance variable in the type definition, it can be used in any
       instance code (instance methods, the constructor, and the destructor) without declaration.
       This differs from normal Tcl practice, in which all non-local variables in a proc need  to
       be declared.

       There  is  a  speed  penalty  to having all instance variables implicitly available in all
       instance code.  Even though your code need not declare the variables explicitly, Snit must
       still  declare  them,  and  that takes time.  If you have ten instance variables, a method
       that uses none of them must still pay the declaration penalty for all ten.  In most cases,
       the  additional runtime cost is negligible.  If extreme cases, you might wish to avoid it;
       there are two methods for doing so.

       The first is to define a single instance  variable,  an  array,  and  store  all  of  your
       instance  data in the array.  This way, you're only paying the declaration penalty for one
       variable--and you probably need the variable most of the time anyway.  This method  breaks
       down  if  your  instance  variables include multiple arrays; in Tcl 8.5, however, the dict
       command might come to your rescue.

       The second method is to declare your instance variables explicitly in your instance  code,
       while not including them in the type definition:

              snit::type dog {
                  constructor {} {
                      variable mood

                      set mood happy
                  }

                  method setmood {newMood} {
                      variable mood

                      set mood $newMood
                  }

                  method getmood {} {
                      variable mood

                      return $mood
                  }
              }

       This allows you to ensure that only the required variables are included in each method, at
       the cost of longer code and run-time errors when you forget  to  declare  a  variable  you
       need.

   HOW DO I PASS AN INSTANCE VARIABLE'S NAME TO ANOTHER OBJECT?
       In  Tk, it's common to pass a widget a variable name; for example, Tk label widgets have a
       -textvariable option which names the variable which will contain the widget's text.   This
       allows  the  program  to  update  the  label's  value just by assigning a new value to the
       variable.

       If you naively pass the instance variable name to the label widget, you'll be confused  by
       the  result;  Tk  will assume that the name names a global variable.  Instead, you need to
       provide a fully-qualified variable name.  From within an instance method or a constructor,
       you can fully qualify the variable's name using the myvar command:

              snit::widget mywidget {
                  variable labeltext ""

                  constructor {args} {
                      # ...

                      label $win.label -textvariable [myvar labeltext]

                      # ...
                  }
              }

   HOW DO I MAKE AN INSTANCE VARIABLE PUBLIC?
       Practically  speaking,  you don't.  Instead, you'll implement public variables as OPTIONS.
       Alternatively, you can write INSTANCE METHODS to set and get the variable's value.

OPTIONS

   WHAT IS AN OPTION?
       A type's options are the equivalent of what other  object-oriented  languages  would  call
       public  member  variables  or  properties: they are data values which can be retrieved and
       (usually) set by the clients of an object.

       Snit's implementation of  options  follows  the  Tk  model  fairly  exactly,  except  that
       snit::type  objects  usually  don't interact with THE TK OPTION DATABASE; snit::widget and
       snit::widgetadaptor objects, on the other hand, always do.

   HOW DO I DEFINE AN OPTION?
       Options are defined in the type definition  using  the  option  statement.   Consider  the
       following type, to be used in an application that manages a list of dogs for a pet store:

              snit::type dog {
                  option -breed -default mongrel
                  option -color -default brown
                  option -akc   -default 0
                  option -shots -default 0
              }

       According  to  this, a dog has four notable properties: a breed, a color, a flag that says
       whether it's pedigreed with the American Kennel Club, and another flag that  says  whether
       it has had its shots.  The default dog, evidently, is a brown mutt.

       There  are a number of options you can specify when defining an option; if -default is the
       only one, you can omit the word -default as follows:

              snit::type dog {
                  option -breed mongrel
                  option -color brown
                  option -akc   0
                  option -shots 0
              }

       If no -default value is specified, the option's default value will  be  the  empty  string
       (but see THE TK OPTION DATABASE).

       The Snit man page refers to options like these as "locally defined" options.

   HOW CAN A CLIENT SET OPTIONS AT OBJECT CREATION?
       The  normal  convention is that the client may pass any number of options and their values
       after the object's name at object creation.  For example, the ::dog command defined in the
       previous  answer can now be used to create individual dogs.  Any or all of the options may
       be set at creation time.

              % dog spot -breed beagle -color "mottled" -akc 1 -shots 1
              ::spot
              % dog fido -shots 1
              ::fido
              %

       So ::spot is a pedigreed beagle; ::fido is a typical mutt, but his owners  evidently  take
       care of him, because he's had his shots.

       Note:  If  the  type  defines  a  constructor,  it can specify a different object-creation
       syntax.  See CONSTRUCTORS for more information.

   HOW CAN A CLIENT RETRIEVE AN OPTION'S VALUE?
       Retrieve option values using the cget method:

              % spot cget -color
              mottled
              % fido cget -breed
              mongrel
              %

   HOW CAN A CLIENT SET OPTIONS AFTER OBJECT CREATION?
       Any number of options may be set at one time using the configure instance method.  Suppose
       that  closer inspection shows that ::fido is not a brown mongrel, but rather a rare Arctic
       Boar Hound of a lovely dun color:

              % fido configure -color dun -breed "Arctic Boar Hound"
              % fido cget -color
              dun
              % fido cget -breed
              Arctic Boar Hound

       Alternatively, the configurelist method takes a list of options and  values;  occasionally
       this is more convenient:

              % set features [list -color dun -breed "Arctic Boar Hound"]
              -color dun -breed {Arctic Boar Hound}
              % fido configurelist $features
              % fido cget -color
              dun
              % fido cget -breed
              Arctic Boar Hound
              %

       In Tcl 8.5, the * keyword can be used with configure in this case:

              % set features [list -color dun -breed "Arctic Boar Hound"]
              -color dun -breed {Arctic Boar Hound}
              % fido configure {*}$features
              % fido cget -color
              dun
              % fido cget -breed
              Arctic Boar Hound
              %

       The results are the same.

   HOW SHOULD AN INSTANCE METHOD ACCESS AN OPTION VALUE?
       There  are  two ways an instance method can set and retrieve an option's value.  One is to
       use the configure and cget methods, as shown below.

              % snit::type dog {
                  option -weight 10

                  method gainWeight {} {
                      set wt [$self cget -weight]
                      incr wt
                      $self configure -weight $wt
                  }
              }
              ::dog
              % dog fido
              ::fido
              % fido cget -weight
              10
              % fido gainWeight
              % fido cget -weight
              11
              %

       Alternatively, Snit provides a built-in  array  instance  variable  called  options.   The
       indices are the option names; the values are the option values.  The method gainWeight can
       thus be rewritten as follows:

                  method gainWeight {} {
                      incr options(-weight)
                  }

       As you can see, using the options variable involves considerably less typing  and  is  the
       usual  way  to  do  it.   But if you use -configuremethod or -cgetmethod (described in the
       following answers), you might wish to use the configure and cget methods anyway,  just  so
       that  any  special processing you've implemented is sure to get done.  Also, if the option
       is delegated to a component then configure and cget are the only way to access it  without
       accessing the component directly.  See DELEGATION for more information.

   HOW CAN I MAKE AN OPTION READ-ONLY?
       Define the option with -readonly yes.

       Suppose  you've  got an option that determines how instances of your type are constructed;
       it must be set at creation time, after which it's constant.   For  example,  a  dog  never
       changes its breed; it might or might not have had its shots, and if not can have them at a
       later time.  -breed should be read-only, but -shots should not be.

              % snit::type dog {
                  option -breed -default mongrel -readonly yes
                  option -shots -default no
              }
              ::dog
              % dog fido -breed retriever
              ::fido
              % fido configure -shots yes
              % fido configure -breed terrier
              option -breed can only be set at instance creation
              %

   HOW CAN I CATCH ACCESSES TO AN OPTION'S VALUE?
       Define a -cgetmethod for the option.

   WHAT IS A -CGETMETHOD?
       A -cgetmethod is a method that's called whenever the related option's value is queried via
       the  cget instance method.  The handler can compute the option's value, retrieve it from a
       database, or do anything else you'd like it to do.

       Here's what the default behavior would look like if written using a -cgetmethod:

              snit::type dog {
                  option -color -default brown -cgetmethod GetOption

                  method GetOption {option} {
                      return $options($option)
                  }
              }

       Any instance method can be used, provided that it takes one  argument,  the  name  of  the
       option whose value is to be retrieved.

   HOW CAN I CATCH CHANGES TO AN OPTION'S VALUE?
       Define a -configuremethod for the option.

   WHAT IS A -CONFIGUREMETHOD?
       A  -configuremethod  is  a method that's called whenever the related option is given a new
       value via the configure or configurelist instance methods. The method can pass  the  value
       on to some other object, store it in a database, or do anything else you'd like it to do.

       Here's  what  the  default  configuration  behavior  would  look  like  if written using a
       -configuremethod:

              snit::type dog {
                  option -color -default brown -configuremethod SetOption

                  method SetOption {option value} {
                      set options($option) $value
                  }
              }

       Any instance method can be used, provided that it takes two arguments,  the  name  of  the
       option and the new value.

       Note  that  if your method doesn't store the value in the options array, the options array
       won't get updated.

   HOW CAN I VALIDATE AN OPTION'S VALUE?
       Define a -validatemethod.

   WHAT IS A -VALIDATEMETHOD?
       A -validatemethod is a method that's called whenever the related option  is  given  a  new
       value   via   the   configure  or  configurelist  instance  methods.   It's  the  method's
       responsibility to determine whether the new value is valid,  and  throw  an  error  if  it
       isn't.   The  -validatemethod, if any, is called before the value is stored in the options
       array; in particular, it's called before the -configuremethod, if any.

       For example, suppose an option always takes a Boolean value.   You  can  ensure  that  the
       value is in fact a valid Boolean like this:

              % snit::type dog {
                  option -shots -default no -validatemethod BooleanOption

                  method BooleanOption {option value} {
                      if {![string is boolean -strict $value]} {
                          error "expected a boolean value, got \"$value\""
                      }
                  }
              }
              ::dog
              % dog fido
              % fido configure -shots yes
              % fido configure -shots NotABooleanValue
              expected a boolean value, got "NotABooleanValue"
              %

       Note that the same -validatemethod can be used to validate any number of boolean options.

       Any  method can be a -validatemethod provided that it takes two arguments, the option name
       and the new option value.

TYPE VARIABLES

   WHAT IS A TYPE VARIABLE?
       A type variable is a private variable associated with a  Snit  type  rather  than  with  a
       particular instance of the type.  In C++ and Java, the term static member variable is used
       for the same notion.  Type variables can be scalars or arrays.

   HOW IS A SCALAR TYPE VARIABLE DEFINED?
       Scalar type variables are defined in the type definition using the typevariable statement.
       You can simply name it, or you can initialize it with a value:

              snit::type mytype {
                  # Define variable "greeting" and initialize it with "Howdy!"
                  typevariable greeting "Howdy!"
              }

       Every object of type mytype now has access to a single variable called greeting.

   HOW IS AN ARRAY-VALUED TYPE VARIABLE DEFINED?
       Array-valued type variables are also defined using the typevariable command; to initialize
       them, include the -array option:

              snit::type mytype {
                  # Define typearray variable "greetings"
                  typevariable greetings -array {
                      formal "Good Evening"
                      casual "Howdy!"
                  }
              }

   WHAT HAPPENS IF I DON'T INITIALIZE A TYPE VARIABLE?
       Variables do not really exist until they are given values.  If you  do  not  initialize  a
       variable  when  you  define it, then you must be sure to assign a value to it (in the type
       constructor, say) before you reference it.

   ARE THERE ANY LIMITATIONS ON TYPE VARIABLE NAMES?
       Type variable names have the same restrictions as the names of INSTANCE VARIABLES do.

   DO I NEED TO DECLARE MY TYPE VARIABLES IN MY METHODS?
       No. Once you've defined a type variable in the type definition, it can be used in INSTANCE
       METHODS  or  TYPE  METHODS without declaration.  This differs from normal Tcl practice, in
       which all non-local variables in a proc need to be declared.

       Type variables are subject to the same speed/readability tradeoffs as instance  variables;
       see Do I need to declare my instance variables in my methods?

   HOW DO I PASS A TYPE VARIABLE'S NAME TO ANOTHER OBJECT?
       In  Tk, it's common to pass a widget a variable name; for example, Tk label widgets have a
       -textvariable option which names the variable which will contain the widget's text.   This
       allows  the  program  to  update  the  label's  value just by assigning a new value to the
       variable.

       If you naively pass a type variable name to the label widget, you'll be  confused  by  the
       result;  Tk  will  assume  that  the  name  names a global variable.  Instead, you need to
       provide a fully-qualified variable name.  From within an instance method or a constructor,
       you can fully qualify the type variable's name using the mytypevar command:

              snit::widget mywidget {
                  typevariable labeltext ""

                  constructor {args} {
                      # ...

                      label $win.label -textvariable [mytypevar labeltext]

                      # ...
                  }
              }

   HOW DO I MAKE A TYPE VARIABLE PUBLIC?
       There  are  two  ways to do this.  The preferred way is to write a pair of TYPE METHODS to
       set and query the type variable's value.

       Type variables are stored in the type's namespace, which has the same  name  as  the  type
       itself.   Thus,  you  can also publicize the type variable's name in your documentation so
       that clients can access it directly.  For example,

              snit::type mytype {
                  typevariable myvariable
              }

              set ::mytype::myvariable "New Value"

TYPE METHODS

   WHAT IS A TYPE METHOD?
       A type method is a procedure associated with the type itself rather than with any specific
       instance of the type, and called as a subcommand of the type command.

   HOW DO I DEFINE A TYPE METHOD?
       Type methods are defined in the type definition using the typemethod statement:

              snit::type dog {
                  # List of pedigreed dogs
                  typevariable pedigreed

                  typemethod pedigreedDogs {} {
                      return $pedigreed
                  }
              }

       Suppose  the  dog type maintains a list of the names of the dogs that have pedigrees.  The
       pedigreedDogs type method returns this list.

       The typemethod statement looks just like a normal Tcl proc, except that it  appears  in  a
       snit::type  definition.   Notice  that  every type method gets an implicit argument called
       type, which contains the fully-qualified type name.

   HOW DOES A CLIENT CALL A TYPE METHOD?
       The type method name becomes a subcommand of the type's command.   For  example,  assuming
       that the constructor adds each pedigreed dog to the list of pedigreedDogs,

              snit::type dog {
                  option -pedigreed 0

                  # List of pedigreed dogs
                  typevariable pedigreed

                  typemethod pedigreedDogs {} {
                      return $pedigreed
                  }

                  # ...
              }

              dog spot -pedigreed 1
              dog fido

              foreach dog [dog pedigreedDogs] { ... }

   ARE THERE ANY LIMITATIONS ON TYPE METHOD NAMES?
       Not  really,  so  long  as  you avoid the standard type method names: create, destroy, and
       info.

   HOW DO I MAKE A TYPE METHOD PRIVATE?
       It's sometimes useful to define private type methods, that is, type methods intended to be
       called only by other type or instance methods of the same object.

       Snit  doesn't  implement  any  access control on type methods; by convention, the names of
       public methods begin with a lower-case letter, and the names of private methods begin with
       an upper-case letter.

       Alternatively, a Snit proc can be used as a private type method; see PROCS.

   ARE THERE ANY LIMITATIONS ON TYPE METHOD ARGUMENTS?
       Method argument lists are defined just like normal Tcl proc argument lists; in particular,
       they can include arguments with default values and the args argument.

       However, every type method is called with an implicit argument called type  that  contains
       the  name of the type command.  In addition, type methods should by convention avoid using
       the names of the arguments implicitly defined for INSTANCE METHODS.

   HOW DOES AN INSTANCE OR TYPE METHOD CALL A TYPE METHOD?
       If an instance or type method needs to call a type method, it should use $type to do so:

              snit::type dog {

                  typemethod pedigreedDogs {} { ... }

                  typemethod printPedigrees {} {
                      foreach obj [$type pedigreedDogs] { ... }
                  }
              }

   HOW DO I PASS A TYPE METHOD AS A CALLBACK?
       It's common in Tcl to pass a snippet of code to another object,  for  it  to  call  later.
       Because  types  cannot  be renamed, you can just use the type name, or, if the callback is
       registered from within a type method, type.  For example, suppose we want to print a  list
       of pedigreed dogs when a Tk button is pushed:

              button .btn -text "Pedigrees" -command [list dog printPedigrees]
              pack .btn

       Alternatively,  from a method or type method you can use the mytypemethod command, just as
       you would use mymethod to define a callback command for INSTANCE METHODS.

   CAN TYPE METHODS BE HIERARCHICAL?
       Yes, you can define hierarchical type methods in just the  same  way  as  you  can  define
       hierarchical instance methods.  See INSTANCE METHODS for more.

PROCS

   WHAT IS A PROC?
       A  Snit  proc  is really just a Tcl proc defined within the type's namespace.  You can use
       procs for private code that isn't related to any particular instance.

   HOW DO I DEFINE A PROC?
       Procs are defined by including a proc statement in the type definition:

              snit::type mytype {
                  # Pops and returns the first item from the list stored in the
                  # listvar, updating the listvar
                 proc pop {listvar} { ... }

                 # ...
              }

   ARE THERE ANY LIMITATIONS ON PROC NAMES?
       Any name can be used, so long as it does not begin with Snit_; names beginning with  Snit_
       are reserved for Snit's own use.  However, the wise programmer will avoid proc names (set,
       list, if, etc.) that would shadow standard Tcl command names.

       proc names, being private, should begin with a capital  letter  according  to  convention;
       however,  as there are typically no public procs in the type's namespace it doesn't matter
       much either way.

   HOW DOES A METHOD CALL A PROC?
       Just like it calls any Tcl command.  For example,

              snit::type mytype {
                  # Pops and returns the first item from the list stored in the
                  # listvar, updating the listvar
                  proc pop {listvar} { ... }

                  variable requestQueue {}

                  # Get one request from the queue and process it.
                  method processRequest {} {
                      set req [pop requestQueue]
                  }
              }

   HOW CAN I PASS A PROC TO ANOTHER OBJECT AS A CALLBACK?
       The myproc command returns a callback command for the proc, just as mymethod  does  for  a
       method.

TYPE CONSTRUCTORS

   WHAT IS A TYPE CONSTRUCTOR?
       A  type  constructor is a body of code that initializes the type as a whole, rather like a
       C++ static initializer.  The body of a type constructor is executed once when the type  is
       defined, and never again.

       A type can have at most one type constructor.

   HOW DO I DEFINE A TYPE CONSTRUCTOR?
       A  type  constructor  is  defined  by  using  the  typeconstructor  statement  in the type
       definition.  For example, suppose the type uses an array-valued type variable as a look-up
       table, and the values in the array have to be computed at start-up.

              % snit::type mytype {
                  typevariable lookupTable

                  typeconstructor {
                      array set lookupTable {key value...}
                  }
              }

CONSTRUCTORS

   WHAT IS A CONSTRUCTOR?
       In  object-oriented  programming,  an object's constructor is responsible for initializing
       the object completely at creation time. The  constructor  receives  the  list  of  options
       passed  to the snit::type command's create method and can then do whatever it likes.  That
       might include computing instance variable values, reading data from files, creating  other
       objects, updating type and instance variables, and so forth.

       The constructor's return value is ignored (unless it's an error, of course).

   HOW DO I DEFINE A CONSTRUCTOR?
       A  constructor  is  defined  by  using  the  constructor statement in the type definition.
       Suppose that it's desired to keep  a  list  of  all  pedigreed  dogs.   The  list  can  be
       maintained  in a type variable and retrieved by a type method.  Whenever a dog is created,
       it can add itself to the list--provided that it's  registered  with  the  American  Kennel
       Club.

              % snit::type dog {
                  option -akc 0

                  typevariable akcList {}

                  constructor {args} {
                      $self configurelist $args

                      if {$options(-akc)} {
                          lappend akcList $self
                      }
                  }

                  typemethod akclist {} {
                      return $akcList
                  }
              }
              ::dog
              % dog spot -akc 1
              ::spot
              % dog fido
              ::fido
              % dog akclist
              ::spot
              %

   WHAT DOES THE DEFAULT CONSTRUCTOR DO?
       If  you  don't provide a constructor explicitly, you get the default constructor, which is
       identical to the explicitly-defined constructor shown here:

              snit::type dog {
                  constructor {args} {
                      $self configurelist $args
                  }
              }

       When the constructor is called, args will be set to the list of arguments that follow  the
       object's  name.  The constructor is allowed to interpret this list any way it chooses; the
       normal convention is to assume that it's a list of option names and values,  as  shown  in
       the  example  above.   If  you  simply  want to save the option values, you should use the
       configurelist method, as shown.

   CAN I CHOOSE A DIFFERENT SET OF ARGUMENTS FOR THE CONSTRUCTOR?
       Yes, you can.  For example, suppose we wanted to be sure that  the  breed  was  explicitly
       stated  for every dog at creation time, and couldn't be changed thereafter.  One way to do
       that is as follows:

              % snit::type dog {
                  variable breed

                  option -color brown
                  option -akc 0

                  constructor {theBreed args} {
                      set breed $theBreed
                      $self configurelist $args
                  }

                  method breed {} { return $breed }
              }
              ::dog
              % dog spot dalmatian -color spotted -akc 1
              ::spot
              % spot breed
              dalmatian

       The drawback is that this syntax is non-standard, and may limit the compatibility of  your
       new  type  with  other  people's  code.   For  example,  Snit  assumes  that it can create
       COMPONENTS using the standard creation syntax.

   ARE THERE ANY LIMITATIONS ON CONSTRUCTOR ARGUMENTS?
       Constructor argument lists are subject to the same limitations as those on instance method
       argument  lists.   It  has the same implicit arguments, and can contain default values and
       the args argument.

   IS THERE ANYTHING SPECIAL ABOUT WRITING THE CONSTRUCTOR?
       Yes.  Writing the constructor can be tricky if you're delegating  options  to  components,
       and  there  are  specific  issues relating to snit::widgets and snit::widgetadaptors.  See
       DELEGATION, WIDGETS, WIDGET ADAPTORS, and THE TK OPTION DATABASE.

DESTRUCTORS

   WHAT IS A DESTRUCTOR?
       A destructor is a special kind of method that's called when an object is destroyed.   It's
       responsible  for  doing  any  necessary  clean-up  when  the  object goes away: destroying
       COMPONENTS, closing files, and so forth.

   HOW DO I DEFINE A DESTRUCTOR?
       Destructors are defined by using the destructor statement in the type definition.

       Suppose we're maintaining a list of pedigreed dogs; then we'll want to remove dogs from it
       when they are destroyed.

              snit::type dog {
                  option -akc 0

                  typevariable akcList {}

                  constructor {args} {
                      $self configurelist $args

                      if {$options(-akc)} {
                          lappend akcList $self
                      }
                  }

                  destructor {
                      set ndx [lsearch $akcList $self]

                      if {$ndx != -1} {
                          set akcList [lreplace $akcList $ndx $ndx]
                      }
                  }

                  typemethod akclist {} {
                      return $akcList
                  }
              }

   ARE THERE ANY LIMITATIONS ON DESTRUCTOR ARGUMENTS?
       Yes; a destructor has no explicit arguments.

   WHAT IMPLICIT ARGUMENTS ARE PASSED TO THE DESTRUCTOR?
       The destructor gets the same implicit arguments that are passed to INSTANCE METHODS: type,
       selfns, win, and self.

   MUST COMPONENTS BE DESTROYED EXPLICITLY?
       Yes and no.

       Any Tk widgets  created  by  a  snit::widget  or  snit::widgetadaptor  will  be  destroyed
       automatically  by  Tk when the megawidget is destroyed, in keeping with normal Tk behavior
       (destroying a parent widget destroys the whole tree).

       Components of normal snit::types, on the other hand, are  never  destroyed  automatically,
       nor  are  non-widget  components  of Snit megawidgets.  If your object creates them in its
       constructor, then it should generally destroy them in its destructor.

   IS THERE ANY SPECIAL ABOUT WRITING A DESTRUCTOR?
       Yes.  If an object's constructor throws an error, the object's destructor will  be  called
       to  clean  up;  this  means  that  the object might not be completely constructed when the
       destructor is called.  This can cause the destructor to throw its own error; the result is
       usually  misleading, confusing, and unhelpful.  Consequently, it's important to write your
       destructor so that it's fail-safe.

       For example, a dog might create a tail component; the component will need to be destroyed.
       But suppose there's an error while processing the creation options--the destructor will be
       called, and there will be no tail to destroy.  The simplest solution is generally to catch
       and ignore any errors while destroying components.

              snit::type dog {
                  component tail

                  constructor {args} {
                      $self configurelist $args

                      set tail [tail %AUTO%]
                  }

                  destructor {
                      catch {$tail destroy}
                  }
              }

COMPONENTS

   WHAT IS A COMPONENT?
       Often  an object will create and manage a number of other objects.  A Snit megawidget, for
       example, will often create a number of Tk widgets.  These objects are  part  of  the  main
       object; it is composed of them, so they are called components of the object.

       But  Snit  also has a more precise meaning for COMPONENT.  The components of a Snit object
       are those objects to which methods or options can be delegated.  (See DELEGATION for  more
       information about delegation.)

   HOW DO I DECLARE A COMPONENT?
       First, you must decide what role a component plays within your object, and give the role a
       name.  Then, you declare the component using its role name and  the  component  statement.
       The  component  statement  declares  an  instance  variable  which  is  used  to store the
       component's command name when the component is created.

       For example, suppose your dog object creates a tail object (the better  to  wag  with,  no
       doubt):

              snit::type dog {
                  component mytail

                  constructor {args} {
                      # Create and save the component's command
                      set mytail [tail %AUTO% -partof $self]
                      $self configurelist $args
                  }

                  method wag {} {
                      $mytail wag
                  }
              }

       As  shown  here,  it  doesn't  matter  what the tail object's real name is; the dog object
       refers to it by its component name.

       The above example shows one way to delegate the wag method to the  mytail  component;  see
       DELEGATION for an easier way.

   HOW IS A COMPONENT NAMED?
       A  component  has  two  names.   The  first  name  is that of the component variable; this
       represents the role the component object plays  within  the  Snit  object.   This  is  the
       component  name  proper,  and is the name used to refer to the component within Snit code.
       The second name is the name of the actual component object created by  the  Snit  object's
       constructor.   This  second  name  is always a Tcl command name, and is referred to as the
       component's object name.

       In the example in the  previous  question,  the  component  name  is  mytail;  the  mytail
       component's  object  name  is  chosen automatically by Snit since %AUTO% was used when the
       component object was created.

   ARE THERE ANY LIMITATIONS ON COMPONENT NAMES?
       Yes.  snit::widget and snit::widgetadaptor objects have a  special  component  called  the
       hull component; thus, the name hull should be used for no other purpose.

       Otherwise,  since component names are in fact instance variable names they must follow the
       rules for INSTANCE VARIABLES.

   WHAT IS AN OWNED COMPONENT?
       An owned component is a component whose object command's lifetime  is  controlled  by  the
       snit::type or snit::widget.

       As  stated  above,  a  component  is an object to which our object can delegate methods or
       options.  Under this definition, our object will usually create its component objects, but
       not  necessarily.   Consider  the  following:  a dog object has a tail component; but tail
       knows that it's part of the dog:

              snit::type dog {
                  component mytail

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

                  destructor {
                      catch {$mytail destroy}
                  }

                  delegate method wagtail to mytail as wag

                  method bark {} {
                      return "$self barked."
                  }
              }

               snit::type tail {
                   component mydog
                   option -partof -readonly yes

                   constructor {args} {
                       $self configurelist $args
                       set mydog $options(-partof)
                   }

                   method wag {} {
                       return "Wag, wag."
                   }

                   method pull {} {
                       $mydog bark
                   }
               }

       Thus, if you ask a dog to wag its tail, it tells its tail to wag;  and  if  you  pull  the
       dog's  tail, the tail tells the dog to bark.  In this scenario, the tail is a component of
       the dog, and the dog is a component of the tail, but the dog owns the  tail  and  not  the
       other way around.

   WHAT DOES THE INSTALL COMMAND DO?
       The  install command creates an owned component using a specified command, and assigns the
       result to the component's instance variable.  For example:

              snit::type dog {
                  component mytail

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

       In a snit::type's code, the install command shown above is equivalent to  the  set  mytail
       command  that's  commented  out.   In  a  snit::widget's  or  snit::widgetadaptor's, code,
       however, the install command also queries THE TK OPTION DATABASE and initializes  the  new
       component's options accordingly.  For consistency, it's a good idea to get in the habit of
       using install for all owned components.

   MUST OWNED COMPONENTS BE CREATED IN THE CONSTRUCTOR?
       No, not necessarily.  In fact, there's no reason why an object can't destroy and  recreate
       a component multiple times over its own lifetime.

   ARE THERE ANY LIMITATIONS ON COMPONENT OBJECT NAMES?
       Yes.

       Component objects which are Tk widgets or megawidgets must have valid Tk window names.

       Component  objects  which are not widgets or megawidgets must have fully-qualified command
       names, i.e., names which include the full namespace of the command.  Note that Snit always
       creates objects with fully qualified names.

       Next,  the object names of components and owned by your object must be unique.  This is no
       problem for widget components, since widget names are  always  unique;  but  consider  the
       following code:

              snit::type tail { ... }

              snit::type dog {
                  delegate method wag to mytail

                  constructor {} {
                      install mytail using tail mytail
                  }
              }

       This  code  uses  the  component  name, mytail, as the component object name.  This is not
       good, and here's why: Snit instance code executes in the Snit type's namespace.   In  this
       case,  the  mytail  component  is created in the ::dog:: namespace, and will thus have the
       name ::dog::mytail.

       Now, suppose you create two dogs.   Both  dogs  will  attempt  to  create  a  tail  called
       ::dog::mytail.  The first will succeed, and the second will fail, since Snit won't let you
       create an object if its name is already a command.   Here  are  two  ways  to  avoid  this
       situation:

       First,  if  the  component type is a snit::type you can specify %AUTO% as its name, and be
       guaranteed to get a unique name.  This is the safest thing to do:

                  install mytail using tail %AUTO%

       If the component type isn't a snit::type you can create  the  component  in  the  object's
       instance namespace:

                  install mytail using tail ${selfns}::mytail

       Make sure you pick a unique name within the instance namespace.

   MUST I DESTROY THE COMPONENTS I OWN?
       That  depends.   When  a  parent  widget  is  destroyed,  all  child widgets are destroyed
       automatically. Thus, if your object is a snit::widget  or  snit::widgetadaptor  you  don't
       need  to  destroy any components that are widgets, because they will generally be children
       or descendants of your megawidget.

       If your object is an instance of snit::type, though, none of its owned components will  be
       destroyed  automatically, nor will be non-widget components of a snit::widget be destroyed
       automatically.  All such owned components must be destroyed explicitly, or they  won't  be
       destroyed at all.

   CAN I EXPOSE A COMPONENT'S OBJECT COMMAND AS PART OF MY INTERFACE?
       Yes,  and  there  are  two  ways  to  do  it.   The most appropriate way is usually to use
       DELEGATION.  Delegation allows you to pass the options and methods you  specify  along  to
       particular components.  This effectively hides the components from the users of your type,
       and ensures good encapsulation.

       However, there are times when it's appropriate, not to mention simpler, just to  make  the
       entire component part of your type's public interface.

   HOW DO I EXPOSE A COMPONENT'S OBJECT COMMAND?
       When  you  declare  the  component, specify the component statement's -public option.  The
       value of this option is the name of a method which will be delegated to  your  component's
       object command.

       For  example,  supposed  you've written a combobox megawidget which owns a listbox widget,
       and you want to make the listbox's entire interface public.  You can do it like this:

              snit::widget combobox {
                   component listbox -public listbox

                   constructor {args} {
                       install listbox using listbox $win.listbox ....
                   }
              }

              combobox .mycombo
              .mycombo listbox configure -width 30

       Your comobox widget, .mycombo, now has  a  listbox  method  which  has  all  of  the  same
       subcommands  as  the  listbox  widget  itself.   Thus,  the  above  code  sets the listbox
       component's width to 30.

       Usually you'll let the method name be the same as the component  name;  however,  you  can
       name it anything you like.

TYPE COMPONENTS

   WHAT IS A TYPE COMPONENT?
       A type component is a component that belongs to the type itself instead of to a particular
       instance of the type.  The relationship between components and type components is the same
       as  the relationship between INSTANCE VARIABLES and TYPE VARIABLES.  Both INSTANCE METHODS
       and TYPE METHODS can be delegated to type components.

       Once you understand COMPONENTS and DELEGATION, type components are just more of the same.

   HOW DO I DECLARE A TYPE COMPONENT?
       Declare a type component using the typecomponent statement.  It  takes  the  same  options
       (-inherit  and  -public)  as  the component statement does, and defines a type variable to
       hold the type component's object command.

       Suppose in your model you've got many dogs, but only one veterinarian.  You might make the
       veterinarian a type component.

              snit::type veterinarian { ... }

              snit::type dog {
                  typecomponent vet

                  # ...
              }

   HOW DO I INSTALL A TYPE COMPONENT?
       Just  use  the set command to assign the component's object command to the type component.
       Because types (even snit::widget types) are not widgets, and do not have  options  anyway,
       the extra features of the install command are not needed.

       You'll usually install type components in the type constructor, as shown here:

              snit::type veterinarian { ... }

              snit::type dog {
                  typecomponent vet

                  typeconstructor {
                      set vet [veterinarian %AUTO%]
                  }
              }

   ARE THERE ANY LIMITATIONS ON TYPE COMPONENT NAMES?
       Yes, the same as on INSTANCE VARIABLES, TYPE VARIABLES, and normal COMPONENTS.

DELEGATION

   WHAT IS DELEGATION?
       Delegation,  simply  put,  is  when  you  pass  a  task  you've  been given to one of your
       assistants.  (You do have assistants, don't you?)  Snit objects can  do  the  same  thing.
       The  following  example  shows one way in which the dog object can delegate its wag method
       and its -taillength option to its tail component.

              snit::type dog {
                  variable mytail

                  option -taillength -configuremethod SetTailOption -cgetmethod GetTailOption

                  method SetTailOption {option value} {
                       $mytail configure $option $value
                  }

                  method GetTailOption {option} {
                       $mytail cget $option
                  }

                  method wag {} {
                      $mytail wag
                  }

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

              }

       This is the hard way to do it, by it demonstrates what delegation is all about.   See  the
       following answers for the easy way to do it.

       Note  that  the  constructor  calls  the  configurelist  method after it creates its tail;
       otherwise, if -taillength appeared in the list of args we'd get an error.

   HOW CAN I DELEGATE A METHOD TO A COMPONENT OBJECT?
       Delegation occurs frequently enough that Snit makes it easy. Any method can  be  delegated
       to  any  component  or  type  component by placing a single delegate statement in the type
       definition.  (See COMPONENTS and TYPE COMPONENTS  for  more  information  about  component
       names.)

       For example, here's a much better way to delegate the dog object's wag method:

              % snit::type dog {
                  delegate method wag to mytail

                  constructor {} {
                      install mytail using tail %AUTO%
                  }
              }
              ::dog
              % snit::type tail {
                  method wag {} { return "Wag, wag, wag."}
              }
              ::tail
              % dog spot
              ::spot
              % spot wag
              Wag, wag, wag.

       This  code has the same effect as the code shown under the previous question: when a dog's
       wag method is called, the call and its arguments are passed  along  automatically  to  the
       tail object.

       Note  that when a component is mentioned in a delegate statement, the component's instance
       variable is  defined  implicitly.   However,  it's  still  good  practice  to  declare  it
       explicitly using the component statement.

       Note  also that you can define a method name using the method statement, or you can define
       it using delegate; you can't do both.

   CAN I DELEGATE TO A METHOD WITH A DIFFERENT NAME?
       Suppose you wanted to delegate the dog's wagtail method to the tail's wag  method.   After
       all you wag the tail, not the dog.  It's easily done:

              snit::type dog {
                  delegate method wagtail to mytail as wag

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

   CAN I DELEGATE TO A METHOD WITH ADDITIONAL ARGUMENTS?
       Suppose  the tail's wag method takes as an argument the number of times the tail should be
       wagged.  You want to  delegate  the  dog's  wagtail  method  to  the  tail's  wag  method,
       specifying that the tail should be wagged exactly three times.  This is easily done, too:

              snit::type dog {
                  delegate method wagtail to mytail as {wag 3}
                  # ...
              }

              snit::type tail {
                  method wag {count} {
                      return [string repeat "Wag " $count]
                  }
                  # ...
              }

   CAN I DELEGATE A METHOD TO SOMETHING OTHER THAN AN OBJECT?
       Normal  method  delegation  assumes  that  you're  delegating a method (a subcommand of an
       object command) to a method  of  another  object  (a  subcommand  of  a  different  object
       command).   But  not  all  Tcl  objects follow Tk conventions, and not everything you'd to
       which you'd like to delegate a method is necessary an object.  Consequently, Snit makes it
       easy  to delegate a method to pretty much anything you like using the delegate statement's
       using clause.

       Suppose your dog simulation stores dogs in a database, each dog as a single  record.   The
       database  API you're using provides a number of commands to manage records; each takes the
       record ID (a string you choose) as its first  argument.   For  example,  saverec  saves  a
       record.   If  you  let  the  record ID be the name of the dog object, you can delegate the
       dog's save method to the saverec command as follows:

              snit::type dog {
                  delegate method save using {saverec %s}
              }

       The %s is replaced with the instance name when the save method is called;  any  additional
       arguments are the appended to the resulting command.

       The  using clause understands a number of other %-conversions; in addition to the instance
       name, you can substitute in the method  name  (%m),  the  type  name  (%t),  the  instance
       namespace  (%n),  the  Tk  window name (%w), and, if a component or typecomponent name was
       given in the delegate statement, the component's object command (%c).

   HOW CAN I DELEGATE A METHOD TO A TYPE COMPONENT OBJECT?
       Just exactly as you would to a component object.  The delegate  method  statement  accepts
       both component and type component names in its to clause.

   HOW CAN I DELEGATE A TYPE METHOD TO A TYPE COMPONENT OBJECT?
       Use  the  delegate  typemethod  statement.   It  works  like  delegate  method, with these
       differences: first, it defines a type method instead of an instance  method;  second,  the
       using clause ignores the %s, %n, and %w %-conversions.

       Naturally,  you can't delegate a type method to an instance component...Snit wouldn't know
       which instance should receive it.

   HOW CAN I DELEGATE AN OPTION TO A COMPONENT OBJECT?
       The first question in this section (see DELEGATION) shows one way to delegate an option to
       a  component;  but this pattern occurs often enough that Snit makes it easy.  For example,
       every tail object has a -length option; we want to allow the creator of a  dog  object  to
       set the tail's length.  We can do this:

              % snit::type dog {
                  delegate option -length to mytail

                  constructor {args} {
                      install mytail using tail %AUTO% -partof $self
                      $self configurelist $args
                  }
              }
              ::dog
              % snit::type tail {
                  option -partof
                  option -length 5
              }
              ::tail
              % dog spot -length 7
              ::spot
              % spot cget -length
              7

       This  produces  nearly the same result as the -configuremethod and -cgetmethod shown under
       the first question in this section: whenever a dog  object's  -length  option  is  set  or
       retrieved, the underlying tail object's option is set or retrieved in turn.

       Note  that  you can define an option name using the option statement, or you can define it
       using delegate; you can't do both.

   CAN I DELEGATE TO AN OPTION WITH A DIFFERENT NAME?
       In the previous answer we delegated the dog's -length option down to its tail.   This  is,
       of  course,  wrong.   The  dog  has  a  length,  and  the  tail has a length, and they are
       different.  What we'd really like to do is give the dog a -taillength option, but delegate
       it to the tail's -length option:

              snit::type dog {
                  delegate option -taillength to mytail as -length

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

   HOW CAN I DELEGATE ANY UNRECOGNIZED METHOD OR OPTION TO A COMPONENT OBJECT?
       It  may  happen  that  a Snit object gets most of its behavior from one of its components.
       This often happens with snit::widgetadaptors, for example, where we wish to  slightly  the
       modify  the  behavior  of  an existing widget.  To carry on with our dog example, however,
       suppose that we have a snit::type called  animal  that  implements  a  variety  of  animal
       behaviors--moving,  eating,  sleeping,  and  so forth.  We want our dog objects to inherit
       these same behaviors, while adding dog-like behaviors of its own.  Here's how we can  give
       a dog methods and options of its own while delegating all other methods and options to its
       animal component:

              snit::type dog {
                  delegate option * to animal
                  delegate method * to animal

                  option -akc 0

                  constructor {args} {
                      install animal using animal %AUTO% -name $self
                      $self configurelist $args
                  }

                  method wag {} {
                      return "$self wags its tail"
                  }
              }

       That's it.  A dog is now an animal that has a -akc option and can wag its tail.

       Note that we don't need to specify the full list of method  names  or  option  names  that
       animal  will receive.  It gets anything dog doesn't recognize--and if it doesn't recognize
       it either, it will simply throw an error, just as it should.

       You can also delegate all  unknown  type  methods  to  a  type  component  using  delegate
       typemethod *.

   HOW CAN I DELEGATE ALL BUT CERTAIN METHODS OR OPTIONS TO A COMPONENT?
       In  the  previous  answer,  we  said that every dog is an animal by delegating all unknown
       methods and options to the animal component. But what if the animal type has some  methods
       or options that we'd like to suppress?

       One  solution  is  to  explicitly  delegate  all  the  options  and methods, and forgo the
       convenience of delegate method * and delegate option *.  But if we wish to suppress only a
       few options or methods, there's an easier way:

              snit::type dog {
                  delegate option * to animal except -numlegs
                  delegate method * to animal except {fly climb}

                  # ...

                  constructor {args} {
                      install animal using animal %AUTO% -name $self -numlegs 4
                      $self configurelist $args
                  }

                  # ...
              }

       Dogs  have  four  legs, so we specify that explicitly when we create the animal component,
       and explicitly exclude -numlegs from the set of delegated options.   Similarly,  dogs  can
       neither fly nor climb, so we exclude those animal methods as shown.

   CAN A HIERARCHICAL METHOD BE DELEGATED?
       Yes; just specify multiple words in the delegated method's name:

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

              snit::type dog {
                  delegate method {tail wag} to mytail
                  delegate method {tail droop} to mytail

                  # ...

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

                  # ...
              }

       Unrecognized  hierarchical methods can also be delegated; the following code delegates all
       subcommands of the "tail" method to the "mytail" component:

              snit::type dog {
                  delegate method {tail *} to mytail

                  # ...
              }

WIDGETS

   WHAT IS A SNIT::WIDGET?
       A snit::widget is the Snit version of what Tcl programmers usually call  a  megawidget:  a
       widget-like  object usually consisting of one or more Tk widgets all contained within a Tk
       frame.

       A snit::widget is also a special kind of snit::type.  Just about everything  in  this  FAQ
       list that relates to snit::types also applies to snit::widgets.

   HOW DO I DEFINE A SNIT::WIDGET?
       snit::widgets  are defined using the snit::widget command, just as snit::types are defined
       by the snit::type command.

       The body of the definition can contain all of the same kinds of statements, plus a  couple
       of others which will be mentioned below.

   HOW DO SNIT::WIDGETS DIFFER FROM SNIT::TYPES?
       •      The  name  of an instance of a snit::type can be any valid Tcl command name, in any
              namespace.  The name of an instance of a snit::widget must be  a  valid  Tk  widget
              name, and its parent widget must already exist.

       •      An  instance  of  a  snit::type  can  be  destroyed  by calling its destroy method.
              Instances of a snit::widget have no destroy method;  use  the  Tk  destroy  command
              instead.

       •      Every  instance  of  a  snit::widget  has  one predefined component called its hull
              component.  The hull is usually a Tk frame or toplevel widget;  any  other  widgets
              created as part of the snit::widget will usually be contained within the hull.

       •      snit::widgets  can  have  their  options  receive default values from THE TK OPTION
              DATABASE.

   WHAT IS A HULL COMPONENT?
       Snit can't create a Tk widget object; only Tk can do that.   Thus,  every  instance  of  a
       snit::widget must be wrapped around a genuine Tk widget; this Tk widget is called the hull
       component.  Snit effectively piggybacks the behavior you define (methods, options, and  so
       forth)  on  top  of  the hull component so that the whole thing behaves like a standard Tk
       widget.

       For snit::widgets the hull component must be a Tk widget that defines the -class option.

       snit::widgetadaptors differ from snit::widgets chiefly in that any kind of widget  can  be
       used as the hull component; see WIDGET ADAPTORS.

   HOW CAN I SET THE HULL TYPE FOR A SNIT::WIDGET?
       A  snit::widget's hull component will usually be a Tk frame widget; however, it may be any
       Tk widget that defines the -class option.  You can explicitly choose  the  hull  type  you
       prefer by including the hulltype command in the widget definition:

              snit::widget mytoplevel {
                  hulltype toplevel

                  # ...
              }

       If no hulltype command appears, the hull will be a frame.

       By  default,  Snit  recognizes the following hull types: the Tk widgets frame, labelframe,
       toplevel, and the Tile widgets ttk::frame, ttk::labelframe, and ttk::toplevel.  To  enable
       the  use of some other kind of widget as the hull type, you can lappend the widget command
       to the variable snit::hulltypes (always provided the widget  defines  the  -class  option.
       For example, suppose Tk gets a new widget type called a prettyframe:

              lappend snit::hulltypes prettyframe

              snit::widget mywidget {
                  hulltype prettyframe

                  # ...
              }

   HOW SHOULD I NAME WIDGETS WHICH ARE COMPONENTS OF A SNIT::WIDGET?
       Every  widget,  whether  a  genuine Tk widget or a Snit megawidget, has to have a valid Tk
       window name.  When a snit::widget is first created, its  instance  name,  self,  is  a  Tk
       window   name;  however,  if  the  snit::widget  is  used  as  the  hull  component  by  a
       snit::widgetadaptor its instance name will be changed to something else.  For this reason,
       every  snit::widget  method,  constructor,  destructor,  and  so  forth  is passed another
       implicit argument, win, which is the window name of the megawidget.  Any  children  should
       be named using win as the root.

       Thus,  suppose  you're writing a toolbar widget, a frame consisting of a number of buttons
       placed side-by-side.  It might look something like this:

              snit::widget toolbar {
                  delegate option * to hull

                  constructor {args} {
                      button $win.open -text Open -command [mymethod open]
                      button $win.save -text Save -command [mymethod save]

                      # ....

                      $self configurelist $args

                  }
              }

       See also the question on renaming objects, toward the top of this file.

WIDGET ADAPTORS

   WHAT IS A SNIT::WIDGETADAPTOR?
       A snit::widgetadaptor is a  kind  of  snit::widget.   Whereas  a  snit::widget's  hull  is
       automatically  created and is always a Tk frame, a snit::widgetadaptor can be based on any
       Tk widget--or on any Snit megawidget, or even (with luck)  on  megawidgets  defined  using
       some other package.

       It's  called  a  widget  adaptor  because  it  allows  you  to take an existing widget and
       customize its behavior.

   HOW DO I DEFINE A SNIT::WIDGETADAPTOR?
       Use the snit::widgetadaptor command.  The definition for a snit::widgetadaptor looks  just
       like  that  for  a snit::type or snit::widget, except that the constructor must create and
       install the hull component.

       For example, the following code creates a read-only text widget by the  simple  device  of
       turning  its  insert and delete methods into no-ops.  Then, we define new methods, ins and
       del, which get delegated to the hull component as insert and delete.  Thus, we've  adapted
       the  text  widget  and  given  it new behavior while still leaving it fundamentally a text
       widget.

              ::snit::widgetadaptor rotext {

                  constructor {args} {
                      # Create the text widget; turn off its insert cursor
                      installhull using text -insertwidth 0

                      # Apply any options passed at creation time.
                      $self configurelist $args
                  }

                  # Disable the text widget's insert and delete methods, to
                  # make this readonly.
                  method insert {args} {}
                  method delete {args} {}

                  # Enable ins and del as synonyms, so the program can insert and
                  # delete.
                  delegate method ins to hull as insert
                  delegate method del to hull as delete

                  # Pass all other methods and options to the real text widget, so
                  # that the remaining behavior is as expected.
                  delegate method * to hull
                  delegate option * to hull
              }

       The most important part is in the constructor.  Whereas snit::widget creates the hull  for
       you,  snit::widgetadaptor  cannot -- it doesn't know what kind of widget you want.  So the
       first thing the constructor does is create the hull component (a Tk text  widget  in  this
       case), and then installs it using the installhull command.

       Note:  There  is  no instance command until you create one by installing a hull component.
       Any attempt to pass methods to $self prior to calling installhull will fail.

   CAN I ADAPT A WIDGET CREATED ELSEWHERE IN THE PROGRAM?
       Yes.

       At times, it can be convenient to adapt a pre-existing widget  instead  of  creating  your
       own.   For  example,  the Bwidget PagesManager widget manages a set of frame widgets, only
       one of which is visible at a time.  The application chooses which frame is  visible.   All
       of  the  These  frames are created by the PagesManager itself, using its add method.  It's
       convenient to adapt these frames to do what we'd like them to do.

       In a case like this, the Tk widget will already  exist  when  the  snit::widgetadaptor  is
       created.  Snit provides an alternate form of the installhull command for this purpose:

              snit::widgetadaptor pageadaptor {
                  constructor {args} {
                      # The widget already exists; just install it.
                      installhull $win

                      # ...
                  }
              }

   CAN I ADAPT ANOTHER MEGAWIDGET?
       Maybe.  If the other megawidget is a snit::widget or snit::widgetadaptor, then yes.  If it
       isn't then, again, maybe.  You'll have to try it and see.   You're  most  likely  to  have
       trouble  with widget destruction--you have to make sure that your megawidget code receives
       the <Destroy> event before the megawidget you're adapting does.

THE TK OPTION DATABASE

   WHAT IS THE TK OPTION DATABASE?
       The Tk option database is a database of default option values  maintained  by  Tk  itself;
       every  Tk  application has one.  The concept of the option database derives from something
       called the X Windows resource database; however, the option database is available in every
       Tk  implementation, including those which do not use the X Windows system (e.g., Microsoft
       Windows).

       Full details about the Tk option database are beyond the  scope  of  this  document;  both
       Practical  Programming  in  Tcl  and  Tk  by Welch, Jones, and Hobbs, and Effective Tcl/Tk
       Programming by Harrison and McClennan., have good introductions to it.

       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  widget's  default  widget  class is not what is desired, set it explicitly
              using the widgetclass statement in the widget definition.

       •      When  defining  or  delegating  options,  specify  the  resource  and  class  names
              explicitly when necessary.

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

       •      Use the install command to create and install all components which are widgets.

       •      Use the install command to create and install components which  aren't  widgets  if
              you'd like them to receive option values from the option database.

       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.

   DO SNIT::TYPES USE THE TK OPTION DATABASE?
       No, they don't; querying the option database requires a Tk window  name,  and  snit::types
       don't have one.

       If  you  create  an  instance  of  a  snit::type  as  a  component  of  a  snit::widget or
       snit::widgetadaptor, on the other hand, and if any options are delegated to the component,
       and if you use install to create and install it, then the megawidget will query the option
       database on the snit::type's behalf.  This might or might not be what you  want,  so  take
       care.

   WHAT IS MY SNIT::WIDGET'S WIDGET CLASS?
       Every  Tk  widget has a "widget class": a name that is used when adding option settings to
       the database.  For Tk widgets, the widget class is the same as  the  widget  command  name
       with an initial capital.  For example, the widget class of the Tk button widget 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:

              snit::widget ::mylibrary::scrolledText {
                  widgetclass Text

                  # ...
              }

       The  above  definition says that a scrolledText megawidget has the same widget class as an
       ordinary text widget.  This might or might not be a good idea, depending on how  the  rest
       of the megawidget is defined, and how its options are delegated.

   WHAT IS MY SNIT::WIDGETADAPTOR'S WIDGET CLASS?
       The  widget  class  of  a snit::widgetadaptor is just the widget class of its hull widget;
       Snit has no control over this.

       Note that the widget class can be changed only for frame and toplevel  widgets,  which  is
       why these are the valid hull types for snit::widgets.

       Try  to  use  snit::widgetadaptors  only  to  make small modifications to another widget's
       behavior.  Then, it will usually not make  sense  to  change  the  widget's  widget  class
       anyway.

   WHAT ARE OPTION RESOURCE AND CLASS NAMES?
       Every  Tk widget 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
       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 Tk 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.

   WHAT ARE THE RESOURCE AND CLASS NAMES FOR MY MEGAWIDGET'S OPTIONS?
       For options implicitly delegated to a component using delegate option *, the resource  and
       class  names will be exactly those defined by the component.  The configure method returns
       these names, along with the option's default and current values:

              % snit::widget mytext {
                  delegate option * to text

                  constructor {args} {
                      install text using text .text
                      # ...
                  }

                  # ...
              }
              ::mytext
              % mytext .text
              .text
              % .text configure -padx
              -padx padX Pad 1 1
              %

       For all other options (whether locally defined or explicitly delegated), the resource  and
       class names can be defined explicitly, or they can be allowed to have default values.

       By default, the resource name is just the option name minus the hyphen; the the class name
       is just the option  name  with  an  initial  capital  letter.   For  example,  suppose  we
       explicitly delegate "-padx":

              % snit::widget mytext {
                  option -myvalue 5

                  delegate option -padx to text
                  delegate option * to text

                  constructor {args} {
                      install text using text .text
                      # ...
                  }

                  # ...
              }
              ::mytext
              % mytext .text
              .text
              % .text configure -myvalue
              -myvalue myvalue Myvalue 5 5
              % .text configure -padx
              -padx padx Padx 1 1
              %

       Here  the  resource and class names are chosen using the default rules.  Often these rules
       are sufficient, but in the case of "-padx" we'd  most  likely  prefer  that  the  option's
       resource  and  class  names  are  the same as for the built-in Tk widgets.  This is easily
       done:

              % snit::widget mytext {
                  delegate option {-padx padX Pad} to text

                  # ...
              }
              ::mytext
              % mytext .text
              .text
              % .text configure -padx
              -padx padX Pad 1 1
              %

   HOW DOES SNIT INITIALIZE MY MEGAWIDGET'S LOCALLY-DEFINED OPTIONS?
       The option database is queried for each of the megawidget's locally-defined options, using
       the  option's  resource  and  class  name.   If  the result isn't "", then it replaces the
       default value given in widget definition.  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".

   HOW DOES SNIT INITIALIZE DELEGATED OPTIONS?
       That depends on whether the options are delegated to the hull, or to some other component.

   HOW DOES SNIT INITIALIZE 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 which 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; the -background option should probably have  been  excluded  using  the  delegate
       statement's except clause, or (more likely) 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, in accordance with the standard Tk naming for this option.
       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.   To  avoid  confusion,  the
       -borderwidth option should have been delegated like this:

                  delegate option {-borderwidth borderWidth BorderWidth} to hull

       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, without
       help from Snit.  Options delegated from a different name are initialized from  the  option
       database in the same way as described above.

       In  earlier  versions of Snit, snit::widgetadaptors were expected to call installhull like
       this:

                  installhull [text $win -foreground white]

       This form still works--but Snit will not query the option database as described above.

   HOW DOES SNIT INITIALIZE OPTIONS DELEGATED TO OTHER COMPONENTS?
       For hull components, Snit assumes that Tk will do most of the  work  automatically.   Non-
       hull components are somewhat more complicated, because they are matched against the option
       database twice.

       A component widget remains a widget still, and is therefore initialized  from  the  option
       database  in the usual way.  A text widget remains a text widget whether it is a component
       of a megawidget or not, and will be created as such.

       But then, 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 (like -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 which were not explicitly included
              in the install command.  For all such options, Snit queries the option database and
              configures the component accordingly.

       You don't really need to know all of this; just use install to  install  your  components,
       and Snit will try to do the right thing.

   WHAT HAPPENS IF I INSTALL A NON-WIDGET AS A COMPONENT OF WIDGET?
       A  snit::type  never  queries  the option database.  However, a snit::widget 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.

       However, when used within a megawidget, install assumes that the created component uses  a
       reasonably standard widget-like creation syntax.  If it doesn't, don't use install.

ENSEMBLE COMMANDS

   WHAT IS AN ENSEMBLE COMMAND?
       An  ensemble  command  is  a  command  with  subcommands.   Snit  objects are all ensemble
       commands; however, the term more usually refers to commands like the standard Tcl commands
       string,  file,  and  clock.   In  a  sense,  these are singleton objects--there's only one
       instance of them.

   HOW CAN I CREATE AN ENSEMBLE COMMAND USING SNIT?
       There are two ways--as a snit::type, or as an instance of a snit::type.

   HOW CAN I CREATE AN ENSEMBLE COMMAND USING AN INSTANCE OF A SNIT::TYPE?
       Define a type whose INSTANCE METHODS are the subcommands of your ensemble command.   Then,
       create an instance of the type with the desired name.

       For  example,  the  following code uses DELEGATION to create a work-alike for the standard
       string command:

              snit::type ::mynamespace::mystringtype {
                  delegate method * to stringhandler

                  constructor {} {
                      set stringhandler string
                  }
              }

              ::mynamespace::mystringtype mystring

       We create the type in a namespace, so that the type command is hidden; then  we  create  a
       single instance with the desired name-- mystring, in this case.

       This  method  has  two drawbacks.  First, it leaves the type command floating about.  More
       seriously, your shiny new ensemble command will have info and destroy subcommands that you
       probably have no use for.  But read on.

   HOW CAN I CREATE AN ENSEMBLE COMMAND USING A SNIT::TYPE?
       Define a type whose TYPE METHODS are the subcommands of your ensemble command.

       For  example,  the  following code uses DELEGATION to create a work-alike for the standard
       string command:

              snit::type mystring {
                  delegate typemethod * to stringhandler

                  typeconstructor {
                      set stringhandler string
                  }
              }

       Now the type command itself is your ensemble command.

       This method has only one drawback, and though it's major, it's  also  surmountable.   Your
       new  ensemble  command will have create, info and destroy subcommands you don't want.  And
       worse yet,  since  the  create  method  can  be  implicit,  users  of  your  command  will
       accidentally be creating instances of your mystring type if they should mispell one of the
       subcommands.  The command will succeed--the first time--but won't do what's wanted.   This
       is very bad.

       The work around is to set some PRAGMAS, as shown here:

              snit::type mystring {
                  pragma -hastypeinfo    no
                  pragma -hastypedestroy no
                  pragma -hasinstances   no

                  delegate typemethod * to stringhandler

                  typeconstructor {
                      set stringhandler string
                  }
              }

       Here  we've  used the pragma statement to tell Snit that we don't want the info typemethod
       or the destroy typemethod, and that our type has no instances; this eliminates the  create
       typemethod  and all related code.  As a result, our ensemble command will be well-behaved,
       with no unexpected subcommands.

PRAGMAS

   WHAT IS A PRAGMA?
       A pragma is an option you can set in your type definitions that affects how  the  type  is
       defined and how it works once it is defined.

   HOW DO I SET A PRAGMA?
       Use  the  pragma  statement.  Each pragma is an option with a value; each time you use the
       pragma statement you can set one or more of them.

   HOW CAN I GET RID OF THE  INFO" TYPE METHOD?"
       Set the -hastypeinfo pragma to no:

              snit::type dog {
                  pragma -hastypeinfo no
                  # ...
              }

       Snit will refrain from defining the info type method.

   HOW CAN I GET RID OF THE  DESTROY" TYPE METHOD?"
       Set the -hastypedestroy pragma to no:

              snit::type dog {
                  pragma -hastypedestroy no
                  # ...
              }

       Snit will refrain from defining the destroy type method.

   HOW CAN I GET RID OF THE  CREATE" TYPE METHOD?"
       Set the -hasinstances pragma to no:

              snit::type dog {
                  pragma -hasinstances no
                  # ...
              }

       Snit will refrain from defining the create type method; if you call the type command  with
       an unknown method name, you'll get an error instead of a new instance of the type.

       This is useful if you wish to use a snit::type to define an ensemble command rather than a
       type with instances.

       Pragmas -hastypemethods and -hasinstances cannot both be  false  (or  there'd  be  nothing
       left).

   HOW CAN I GET RID OF TYPE METHODS ALTOGETHER?
       Normal  Tk  widget type commands don't have subcommands; all they do is create widgets--in
       Snit terms, the type command calls the create type  method  directly.   To  get  the  same
       behavior from Snit, set the -hastypemethods pragma to no:

              snit::type dog {
                  pragma -hastypemethods no
                  #...
              }

              # Creates ::spot
              dog spot

              # Tries to create an instance called ::create
              dog create spot

       Pragmas  -hastypemethods  and  -hasinstances  cannot  both be false (or there'd be nothing
       left).

   WHY CAN'T I CREATE AN OBJECT THAT REPLACES AN OLD OBJECT WITH THE SAME NAME?
       Up until Snit 0.95, you could use any name for an instance of a snit::type,  even  if  the
       name  was already in use by some other object or command.  You could do the following, for
       example:

              snit::type dog { ... }

              dog proc

       You now have a new dog named "proc", which is  probably  not  something  that  you  really
       wanted to do.  As a result, Snit now throws an error if your chosen instance name names an
       existing command.  To restore the old behavior, set the -canreplace pragma to yes:

              snit::type dog {
                  pragma -canreplace yes
                  # ...
              }

   HOW CAN I MAKE MY SIMPLE TYPE RUN FASTER?
       In Snit 1.x, you can set the -simpledispatch pragma to yes.

       Snit 1.x method dispatch is both flexible and fast,  but  the  flexibility  comes  with  a
       price.   If  your  type doesn't require the flexibility, the -simpledispatch pragma allows
       you to substitute a simpler  dispatch  mechanism  that  runs  quite  a  bit  faster.   The
       limitations are these:

       •      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.

       In  Snit  2.2,  the  -simpledispatch  macro  is obsolete, and ignored; all Snit 2.2 method
       dispatch is faster than Snit 1.x's -simpledispatch.

MACROS

   WHAT IS A MACRO?
       A Snit macro is nothing more than a Tcl proc that's defined in the Tcl interpreter used to
       compile Snit type definitions.

   WHAT ARE MACROS GOOD FOR?
       You  can  use Snit macros to define new type definition syntax, and to support conditional
       compilation.

   HOW DO I DO CONDITIONAL COMPILATION?
       Suppose you want your type to use a fast C extension if it's available; otherwise,  you'll
       fallback  to  a  slower  Tcl implementation.  You want to define one set of methods in the
       first case, and another set in the second case.  But how can  your  type  definition  know
       whether the fast C extension is available or not?

       It's  easily  done.   Outside of any type definition, define a macro that returns 1 if the
       extension is available, and 0 otherwise:

              if {$gotFastExtension} {
                  snit::macro fastcode {} {return 1}
              } else {
                  snit::macro fastcode {} {return 0}
              }

       Then, use your macro in your type definition:

              snit::type dog {

                  if {[fastcode]} {
                      # Fast methods
                      method bark {} {...}
                      method wagtail {} {...}
                  } else {
                      # Slow methods
                      method bark {} {...}
                      method wagtail {} {...}
                  }
              }

   HOW DO I DEFINE NEW TYPE DEFINITION SYNTAX?
       Use a macro.  For example, your snit::widget's -background option should be propagated  to
       a number of component widgets.  You could implement that like this:

              snit::widget mywidget {
                  option -background -default white -configuremethod PropagateBackground

                  method PropagateBackground {option value} {
                      $comp1 configure $option $value
                      $comp2 configure $option $value
                      $comp3 configure $option $value
                  }
              }

       For  one  option,  this is fine; if you've got a number of options, it becomes tedious and
       error prone.  So package it as a macro:

              snit::macro propagate {option "to" components} {
                  option $option -configuremethod Propagate$option

                  set body "\n"

                  foreach comp $components {
                      append body "\$$comp configure $option \$value\n"
                  }

                  method Propagate$option {option value} $body
              }

       Then you can use it like this:

              snit::widget mywidget {
                  option -background default -white
                  option -foreground default -black

                  propagate -background to {comp1 comp2 comp3}
                  propagate -foreground to {comp1 comp2 comp3}
              }

   ARE THERE ARE RESTRICTIONS ON MACRO NAMES?
       Yes, there are.  You can't redefine any standard Tcl  commands  or  Snit  type  definition
       statements.   You  can  use  any  other  command  name, including the name of a previously
       defined macro.

       If you're using Snit macros in your application, go ahead and  name  them  in  the  global
       namespace, as shown above.  But if you're using them to define types or widgets for use by
       others, you should define your macros in the same namespace  as  your  types  or  widgets.
       That way, they won't conflict with other people's macros.

       If my fancy snit::widget is called ::mylib::mywidget, for example, then I should define my
       propagate macro as ::mylib::propagate:

              snit::macro mylib::propagate {option "to" components} { ... }

              snit::widget ::mylib::mywidget {
                  option -background default -white
                  option -foreground default -black

                  mylib::propagate -background to {comp1 comp2 comp3}
                  mylib::propagate -foreground to {comp1 comp2 comp3}
              }

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,  adaptors, class, mega widget, object, object oriented, widget,
       widget adaptors

CATEGORY

       Programming tools

COPYRIGHT

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