commit a copy of snit
[scpubgit/TenDotTcl.git] / snit / snitfaq.man
diff --git a/snit/snitfaq.man b/snit/snitfaq.man
new file mode 100644 (file)
index 0000000..945aacf
--- /dev/null
@@ -0,0 +1,4159 @@
+[comment {-*- tcl -*- doctools manpage}]
+[manpage_begin snitfaq n 2.2]
+[copyright {2003-2006, by William H. Duquette}]
+[moddesc {Snit's Not Incr Tcl, OO system}]
+[titledesc   {Snit Frequently Asked Questions}]
+[category  {Programming tools}]
+[description]
+[para]
+
+[section OVERVIEW]
+
+[subsection {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 [cmd snit] man page.
+
+[subsection {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.
+
+[para]
+
+The primary purpose of Snit is to be [term "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.
+
+[para]
+
+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. 
+
+[para]
+
+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 [emph 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. 
+
+[para]
+
+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. 
+
+[subsection {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 [sectref {SNIT VERSIONS}] for the differences between Snit
+1.3 and Snit 2.2.
+
+[subsection {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,
+[uri http://www.wjduquette.com/snit].
+
+[subsection {What are Snit's goals?}]
+
+[para]
+
+[list_begin itemized]
+[item]
+
+A Snit object should be at least as efficient as a hand-coded Tcl
+object (see [uri http://www.wjduquette.com/tcl/objects.html]).
+
+[item]
+
+The fact that Snit was used in an object's implementation should be
+transparent (and irrelevant) to clients of that object.
+
+[item]
+
+Snit should be able to encapsulate objects from other sources,
+particularly Tk widgets.
+
+[item]
+
+Snit megawidgets should be (to the extent possible) indistinguishable
+in interface from Tk widgets.
+
+[item]
+
+Snit should be Tclish--that is, rather than trying to emulate C++,
+Smalltalk, or anything else, it should try to emulate Tcl itself.
+
+[item]
+
+It should have a simple, easy-to-use, easy-to-remember syntax.
+
+[list_end]
+
+[subsection {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.
+
+[para]
+
+Note that you can achieve the effect of inheritance using 
+[sectref COMPONENTS] and [sectref "DELEGATION"]--and you can inherit
+from anything that looks like a Tcl object.
+
+[subsection {What can I do with Snit?}]
+
+Using Snit, a programmer can:
+
+[list_begin itemized]
+[item]
+
+Create abstract data types and Tk megawidgets.
+
+[item]
+
+Define instance variables, type variables, and Tk-style options.
+
+[item]
+
+Define constructors, destructors, instance methods, type methods, procs.
+
+[item]
+
+Assemble a type out of component types.  Instance methods and options
+can be delegated to the component types automatically.
+
+[list_end]
+
+[section {SNIT VERSIONS}]
+
+[subsection {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.
+
+[para]
+
+Snit 1.3, on the other hand, lacks Snit 2.2's optimizations, but
+requires only Tcl 8.3 and later.
+
+[para]
+
+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.
+
+[subsection {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:
+
+[example {package require snit 1.3
+}]
+
+To always use Snit 2.2 (or a later version of Snit 2.x), say this
+instead:
+
+[example {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.
+
+[para]
+
+If you wish your application to always use the latest available
+version of Snit, don't specify a version number:
+
+[example {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.
+
+[subsection {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 
+[cmd "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.
+
+[para]
+
+There are four specific incompatibilities between Snit 1.3 and Snit 2.2.
+
+[para]
+
+[list_begin itemized]
+[item]
+
+Snit 1.3 supports implicit naming of objects.  Suppose you define a
+new [cmd snit::type] called [cmd dog].  You can create instances of
+[cmd dog] in three ways:
+
+[example {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 [cmd "namespace ensemble"]
+mechanism; and [cmd "namespace ensemble"] doesn't allow an ensemble command
+to be called without a subcommand.  In short, using 
+[cmd "namespace ensemble"] there's no way to support implicit naming.
+
+[para]
+
+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 
+[cmd "namespace ensemble"] is not used.  In this case, implicit naming
+is still possible.
+
+[para]
+
+In short, you can have implicit naming if you're willing to do without
+type methods (including the standard type methods, like 
+[cmd "\$type info"]).  To do so, use the [const -hastypemethods] pragma:
+
+[example {pragma -hastypemethods 0}]
+
+[item]
+Hierarchical methods and type methods are implemented differently in
+Snit 2.2.  
+
+[para]
+
+A hierarchical method is an instance method which has
+subcommands; these subcommands are themselves methods.  The Tk text
+widget's [cmd 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:
+
+[example {method {tag configure} {tag args} { ... }
+
+method {tag cget} {tag option} {...}
+}]
+
+Here we've implicitly defined a [cmd tag] method which has two
+subcommands, [cmd configure] and [cmd cget].
+
+[para]
+
+In Snit 1.3, hierarchical methods could be called in two ways:
+
+[example {$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.
+
+[para]
+
+In Snit 2.2 this is no longer the case, and the "weird" way of calling
+hierarchical methods and type methods no longer works.
+
+[item]
+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, [cmd "\$obj info methods"] returned the
+full names of all hierarchical methods.  In the example above, 
+the list returned by [cmd "\$obj info methods"] would include
+[cmd "tag configure"] and [cmd "tag cget"] but not [cmd "tag"], since
+[cmd "tag"] is defined only implicitly.
+
+[para]
+
+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 [cmd "\$obj info methods"] would include [cmd "tag"] but not
+[cmd "tag configure"] or [cmd "tag cget"].
+
+
+[item]
+The fourth incompatibility is due to a new feature.  Snit 2.2 uses
+the new [cmd "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 [cmd "mypackage"] which defines a number of commands
+including a type, [cmd "::mypackage::mytype"].  Thanks to 
+[cmd "namespace path"], the type's code can call any of the other
+commands defined in [cmd "::mypackage::"].
+
+[para]
+
+This is extremely convenient.  However, it also means that commands
+defined in the parent namespace, [cmd "::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
+[cmd "::tie::std::file"].  This type's code calls the standard
+[cmd "file"] command.  When run with Snit 2.2, the code broke--
+the type's command, [cmd "::tie::std::file"], is itself a command
+in the type's parent namespace, and so instead of calling 
+the standard [cmd "file"] command, the type found itself calling
+itself.
+
+[list_end]
+
+[subsection {Are there other differences between Snit 1.x and Snit 2.2?}]
+
+Yes.
+
+[list_begin itemized]
+[item]
+Method dispatch is considerably faster.
+
+[item]
+Many error messages and stack traces are cleaner.
+
+[item]
+The [const -simpledispatch] pragma is obsolete, and ignored if
+present. In Snit 1.x, [const -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 
+[const -simpledispatch] is no longer needed.
+
+[item]
+
+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 [cmd ::parentns::mytype]'s code can call
+[cmd ::parentns::someproc] as just [cmd someproc].
+
+[para]
+
+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.
+
+[para]
+
+This feature depends on the new Tcl 8.5 [cmd "namespace path"] command,
+which is why it hasn't been implemented for V1.x.  V1.x code can
+achieve something similar by placing
+
+[example {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.
+
+[list_end]
+
+
+[section OBJECTS]
+
+[subsection {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.
+
+[para]
+
+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 [method configure] and 
+[method cget] methods.  Snit uses the same conventions as Tk widgets do.
+
+[subsection {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 [term class] is
+usually used instead of [term {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 
+[term {object-based}] programming as opposed to object-oriented
+programming.  Note that you can easily create the effect of 
+inheritance using [sectref COMPONENTS] and [sectref "DELEGATION"].
+
+[para]
+
+In Snit, as in Tk, a [term type] is a command that creates instances
+-- objects -- which belong to the type.  Most types define some number
+of [term options] which can be set at creation time, and usually can be
+changed later.
+
+[para]
+
+Further, an [term 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 [method insert]
+subcommand:
+
+[para]
+[example {    # Create a text widget and insert some text in it.
+    text .mytext -width 80 -height 24
+    .mytext insert end "Howdy!"
+}]
+[para]
+
+In this example, [cmd text] is the [term type] command and
+[cmd .mytext] is the [term instance] command.
+
+[para]
+
+In Snit, object subcommands are generally called 
+[sectref "INSTANCE METHODS"].
+
+[subsection {What kinds of abstract data types does Snit provide?}]
+
+Snit allows you to define three kinds of abstract data type:
+
+[para]
+
+[list_begin itemized]
+[item]
+
+[cmd snit::type]
+[item]
+
+[cmd snit::widget]
+[item]
+
+[cmd snit::widgetadaptor]
+[list_end]
+
+
+[subsection {What is a snit::type?}]
+
+A [cmd snit::type] is a non-GUI abstract data type, e.g., a stack or a
+queue.  [cmd snit::type]s are defined using the [cmd snit::type]
+command.  For example, if you were designing a kennel management
+system for a dog breeder, you'd need a dog type.
+
+[para]
+[example {% snit::type dog {
+    # ...
+}
+::dog
+%
+}]
+[para]
+
+This definition defines a new command ([cmd ::dog], in this case)
+that can be used to define dog objects.
+
+[para]
+
+An instance of a [cmd snit::type] can have [sectref {INSTANCE METHODS}],
+[sectref {INSTANCE VARIABLES}], [sectref OPTIONS], and [sectref COMPONENTS].
+The type itself can have [sectref {TYPE METHODS}],
+[sectref {TYPE VARIABLES}], [sectref {TYPE COMPONENTS}], and 
+[sectref PROCS]. 
+
+
+[subsection {What is a snit::widget?, the short story}]
+
+A [cmd snit::widget] is a Tk megawidget built using Snit; it is very
+similar to a [cmd snit::type].  See [sectref WIDGETS].
+
+
+[subsection {What is a snit::widgetadaptor?, the short story}]
+
+A [cmd 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 [cmd snit::widget].
+See [sectref {WIDGET ADAPTORS}].
+
+
+[subsection {How do I create an instance of a snit::type?}]
+
+You create an instance of a [cmd snit::type] by passing the new
+instance's name to the type's create method.  In the following
+example, we create a [cmd dog] object called [cmd spot].
+
+[para]
+[example {% snit::type dog {
+    # ....
+}
+::dog
+% dog create spot
+::spot
+%
+}]
+[para]
+
+In general, the [method create] method name can be omitted so long as
+the instance name doesn't conflict with any defined 
+[sectref {TYPE METHODS}]. (See [sectref {TYPE COMPONENTS}] for the
+special case in which this doesn't work.)
+So the following example is identical to the
+previous example:
+
+[para]
+[example {% snit::type dog {
+    # ....
+}
+::dog
+% dog spot
+::spot
+%
+}]
+[para]
+
+This document generally uses the shorter form.
+
+[para]
+
+If the [cmd dog] type defines [sectref OPTIONS], these can usually be 
+given defaults at creation time:
+
+[para]
+[example {% 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
+%
+}]
+[para]
+
+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:
+
+[para]
+[example {% spot bark
+::spot barks.
+%
+}]
+[para]
+
+[subsection {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,
+
+[para]
+[example {% snit::type dog { ... }
+::dog
+% set d [dog spot -breed dalmation -color spotted]
+::spot
+% $d cget -breed
+dalmation
+% $d bark
+::spot barks.
+%
+}]
+[para]
+
+If you prefer this style, you might prefer to have Snit
+generate the instance's name automatically.
+
+[subsection {How can I generate the object name automatically?}]
+
+If you'd like Snit to generate an object name for you,
+use the [const %AUTO%] keyword as the requested name:
+
+[para]
+[example {% snit::type dog { ... }
+::dog
+% set d [dog %AUTO%]
+::dog2
+% $d bark
+::dog2 barks.
+%
+}]
+[para]
+
+The [const %AUTO%] keyword can be embedded in a longer string:
+
+[para]
+[example {% set d [dog obj_%AUTO%]
+::obj_dog4
+% $d bark
+::obj_dog4 barks.
+%
+}]
+[para]
+
+
+[subsection {Can types be renamed?}]
+
+Tcl's [cmd 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.
+
+[para]
+
+[cmd snit::type] commands, however, should never be renamed; to do so breaks
+the connection between the type and its objects.
+
+[subsection {Can objects be renamed?}]
+
+Tcl's [cmd 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.
+
+[para]
+
+All Snit objects (including [term widgets] and [term widgetadaptors])
+can be renamed, though this flexibility has some consequences:
+
+[para]
+
+[list_begin itemized]
+[item]
+
+In an instance method, the implicit argument [var self] will always
+contain the object's current name, so instance methods can always call
+other instance methods using [var \$self].
+
+[item]
+
+If the object is renamed, however, then [var \$self]'s value will change.
+Therefore, don't use [var \$self] for anything that will break if 
+[var \$self] changes. For example, don't pass a callback command to
+another object like this:
+
+[example {
+    .btn configure -command [list $self ButtonPress]
+}]
+
+You'll get an error if [cmd .btn] calls your command after your object is
+renamed.
+
+[item]
+
+Instead, your object should define its callback command like this:
+
+[example {
+    .btn configure -command [mymethod ButtonPress]
+}]
+
+The [cmd 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.
+
+[item]
+
+Every object has a private namespace; the name of this namespace is
+available in method bodies, etc., as the value of the implicit
+argument [var selfns].  This value is constant for the life of the
+object.  Use [var \$selfns] instead of [var \$self] if you need a 
+unique token to identify the object.
+
+[item]
+
+When a [cmd 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 [var win].  
+This value is constant for the
+life of the object.  When creating child windows, it's best to use
+[var {$win.child}] rather than [var {$self.child}] as the name of the
+child window.
+
+[list_end]
+
+[subsection {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 [cmd rename] command.
+
+[para]
+
+Snit megawidgets (i.e., instances of [cmd snit::widget] and
+[cmd snit::widgetadaptor]) can be destroyed like any other widget: by
+using the Tk [cmd destroy] command on the widget or on one of its
+ancestors in the window hierarchy.
+
+[para]
+
+Every instance of a [cmd snit::type] has a [method destroy] method:
+
+[para]
+[example {% snit::type dog { ... }
+::dog
+% dog spot
+::spot
+% spot bark
+::spot barks.
+% spot destroy
+% spot barks
+invalid command name "spot"
+%
+}]
+[para]
+
+Finally, every Snit type has a type method called [method destroy]; calling it
+destroys the type and all of its instances:
+
+[example {% 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"
+%
+}]
+
+[section {INSTANCE METHODS}]
+
+[subsection {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.
+
+[subsection {How do I define an instance method?}]
+
+Instance methods are defined in the type definition using
+the [cmd method] statement.  Consider the following code that might be
+used to add dogs to a computer simulation:
+
+[para]
+[example {% snit::type dog {
+    method bark {} {
+        return "$self barks."
+    }
+
+    method chase {thing} {
+        return "$self chases $thing."
+    }
+}
+::dog
+%
+}]
+[para]
+
+A dog can bark, and it can chase things.
+
+[para]
+
+The [cmd method] statement looks just like a normal Tcl [cmd proc],
+except that it appears in a [cmd snit::type] definition.  Notice that
+every instance method gets an implicit argument called [var self];
+this argument contains the object's name.  (There's more on
+implicit method arguments below.)
+
+[subsection {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:
+
+[para]
+[example {% dog spot
+::spot
+% spot bark
+::spot barks.
+% spot chase cat
+::spot chases cat.
+%
+}]
+[para]
+
+[subsection {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 [var self].
+
+[para]
+
+Suppose, for example, that our dogs never chase anything without
+barking at them:
+
+[para]
+[example {% 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.
+%
+}]
+[para]
+
+[subsection {Are there any limitations on instance method names?}]
+
+Not really, so long as you avoid the standard instance method names:
+[method configure], [method configurelist], [method cget],
+[method destroy], and [method info].  Also, method names consisting of 
+multiple words define hierarchical methods.
+
+[subsection {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 [cmd text] widget's [cmd tag] method are hierarchical methods.
+
+[subsection {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 [cmd tag] method with subcommands [cmd cget] and 
+[cmd configure]:
+
+[example {snit::widget mytext {
+    method {tag configure} {tag args} { ... }
+
+    method {tag cget} {tag option} {...}
+}
+}]
+
+Note that there is no explicit definition for the [cmd tag] method;
+it is implicit in the definition of [cmd "tag configure"] and
+[cmd "tag cget"].  If you tried to define [cmd tag] explicitly in this
+example, you'd get an error.
+
+[subsection {How do I call hierarchical methods?}]
+
+As subcommands of subcommands.
+
+[example {% mytext .text
+.text
+% .text tag configure redtext -foreground red -background black
+% .text tag cget redtext -foreground
+red
+%
+}]
+
+[subsection {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.
+
+[para]
+
+Snit doesn't implement any access control on instance methods, so all
+methods are [emph {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.
+
+[para]
+
+For example, suppose our simulated dogs only bark in response to other
+stimuli; they never bark just for fun.  So the [method bark] method
+becomes [method Bark] to indicate that it is private:
+
+[para]
+[example {% 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.
+%
+}]
+[para]
+
+[subsection {Are there any limitations on instance method arguments?}]
+
+Method argument lists are defined just like normal Tcl [cmd proc] argument
+lists; in particular, they can include arguments with default values
+ and the [var args] argument.
+
+[para]
+
+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.
+
+[subsection {What implicit arguments are passed to each instance method?}]
+
+The arguments implicitly passed to every method are [var type],
+[var selfns], [var win], and [var self].
+
+[subsection {What is $type?}]
+
+The implicit argument [var type] contains the fully qualified name of
+the object's type:
+
+[para]
+[example {% snit::type thing {
+    method mytype {} {
+        return $type
+    }
+}
+::thing
+% thing something
+::something
+% something mytype
+::thing
+%
+}]
+[para]
+
+[subsection {What is $self?}]
+
+The implicit argument [var self] contains the object's fully
+qualified name.
+
+[para]
+
+If the object's command is renamed, then [var \$self] will change to
+match in subsequent calls.  Thus, your code should not assume that
+[var \$self] is constant unless you know for sure that the object
+will never be renamed.
+
+[para]
+[example {% snit::type thing {
+    method myself {} {
+        return $self
+    }
+}
+::thing
+% thing mutt
+::mutt
+% mutt myself
+::mutt
+% rename mutt jeff
+% jeff myself
+::jeff
+%
+}]
+[para]
+
+[subsection {What is $selfns?}]
+
+Each Snit object has a private namespace in which to store its
+[sectref {INSTANCE VARIABLES}] and [sectref OPTIONS].  The implicit argument
+[var 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:
+
+[para]
+[example {% snit::type thing {
+    method myNameSpace {} {
+        return $selfns
+    }
+}
+::thing
+% thing jeff
+::jeff
+% jeff myNameSpace
+::thing::Snit_inst3
+% rename jeff mutt
+% mutt myNameSpace
+::thing::Snit_inst3
+%
+}]
+[para]
+
+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.
+
+[subsection {What is $win?}]
+
+The implicit argument [var win] is defined for all Snit methods,
+though it really makes sense only for those of 
+[sectref WIDGETS] and [sectref {WIDGET ADAPTORS}].  [var \$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.
+
+[para]
+
+When a [cmd 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.
+
+[para]
+
+Thus, using [var win] whenever the Tk window name is called for
+means that a [cmd snit::widget] or [cmd snit::widgetadaptor] can be
+adapted by a [cmd snit::widgetadaptor].  See [sectref WIDGETS] for
+more information.
+
+[subsection {How do I pass an instance method as a callback?}]
+
+It depends on the context.
+
+[para]
+
+Suppose in my application I have a [cmd dog] object named [cmd fido],
+and I want [cmd fido] to bark when a Tk button called [cmd .bark] is 
+pressed.  In this case, I create the callback command in the usual
+way, using [cmd list]:
+
+[para]
+[example {    button .bark -text "Bark!" -command [list fido bark]
+}]
+[para]
+
+In typical Tcl style, we use a callback to hook two independent
+components together.  But suppose that the [cmd dog] object has
+a graphical interface and owns the button itself?  In this case,
+the [cmd dog] must pass one of its own instance methods to the
+button it owns.  The obvious thing to do is this:
+
+[para]
+[example {% snit::widget dog {
+    constructor {args} {
+        #...
+        button $win.barkbtn -text "Bark!" -command [list $self bark]
+        #...
+    }
+}
+::dog
+%
+}]
+[para]
+
+(Note that in this example, our [cmd dog]
+becomes a [cmd snit::widget], because it has GUI behavior.  See
+[sectref WIDGETS] for more.)  Thus, if we create a [cmd dog] called
+[cmd .spot], it will create a Tk button called [cmd .spot.barkbtn];
+when pressed, the button will call [cmd {$self bark}].
+
+[para]
+
+Now, this will work--provided that [cmd .spot] is never renamed to
+something else.  But surely renaming widgets is
+abnormal?  And so it is--unless [cmd .spot] is the hull component of a
+[cmd snit::widgetadaptor].  If it is, then it will be renamed, and
+[cmd .spot] will become the name of the [cmd snit::widgetadaptor]
+object.  When the button is pressed, the command [cmd {$self bark}]
+will be handled by the [cmd snit::widgetadaptor], which might or might
+not do the right thing.
+
+[para]
+
+There's a safer way to do it, and it looks like this:
+
+[para]
+[example {% snit::widget dog {
+    constructor {args} {
+        #...
+        button $win.barkbtn -text "Bark!" -command [mymethod bark]
+        #...
+    }
+}
+::dog
+%
+}]
+[para]
+
+The command [cmd mymethod] takes any number of arguments, and can be
+used like [cmd list] to build up a callback command; the only
+difference is that [cmd mymethod] returns a 
+form of the command that won't change even if the instance's name
+changes.
+
+[para]
+
+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 [cmd "\[list \$self bark\]"] will do what you want...but
+this is a technique which should be used only in carefully controlled
+circumstances.
+
+[subsection {How do I delegate instance methods to a component?}]
+
+See [sectref DELEGATION].
+
+[section {INSTANCE VARIABLES}]
+
+
+[subsection {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.
+
+
+[subsection {How is a scalar instance variable defined?}]
+
+Scalar instance variables are defined in the type definition using the
+[cmd variable] statement.  You can simply name it, or you can
+initialize it with a value:
+
+[para]
+[example {snit::type mytype {
+    # Define variable "greeting" and initialize it with "Howdy!"
+    variable greeting "Howdy!"
+}
+}]
+[para]
+
+[subsection {How is an array instance variable defined?}]
+
+Array instance variables are also defined in the type definition
+using the [cmd variable] command.  You can initialize them at the same
+time by specifying the [const -array] option:
+
+[para]
+[example {snit::type mytype {
+    # Define array variable "greetings"
+    variable greetings -array {
+        formal "Good Evening"
+        casual "Howdy!"
+    }
+}
+}]
+[para]
+
+[subsection {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.
+
+[subsection {Are there any limitations on instance variable names?}]
+
+Just a few.
+
+[para]
+
+First, every Snit object has a built-in instance variable called
+[var options], which should never be redefined.
+
+[para]
+
+Second, all names beginning with "Snit_" are reserved for
+use by Snit internal code.
+
+[para]
+
+Third, instance variable names containing the namespace delimiter
+([const ::]) are likely to cause great confusion.
+
+
+[subsection {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.
+
+[para]
+
+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.
+
+[para]
+
+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 [cmd dict] command might come to your rescue.
+
+[para]
+
+The second method is to declare your instance variables explicitly
+in your instance code, while [emph not] including them in the type
+definition:
+
+[example {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.
+
+[subsection {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 [option -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.
+
+[para]
+
+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 [cmd myvar] command:
+
+[para] 
+[example {snit::widget mywidget {
+    variable labeltext ""
+
+    constructor {args} {
+        # ...
+
+        label $win.label -textvariable [myvar labeltext]
+
+        # ...
+    }
+}
+}]
+[para]
+
+[subsection {How do I make an instance variable public?}]
+
+Practically speaking, you don't.  Instead, you'll implement public
+variables as [sectref OPTIONS].
+
+Alternatively, you can write [sectref {INSTANCE METHODS}] to set and get
+the variable's value.
+
+[section OPTIONS]
+
+[subsection {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.
+
+[para]
+
+Snit's implementation of options follows the Tk model fairly exactly,
+except that [cmd snit::type] objects usually don't interact with 
+[sectref "THE TK OPTION DATABASE"]; [cmd snit::widget] and 
+[cmd snit::widgetadaptor] objects, on the other hand, always do.
+
+[subsection {How do I define an option?}]
+
+Options are defined in the type definition using the [cmd option]
+statement.  Consider the following type, to be used in an application
+that manages a list of dogs for a pet store:
+
+[para]
+[example {snit::type dog {
+    option -breed -default mongrel
+    option -color -default brown
+    option -akc   -default 0
+    option -shots -default 0
+}
+}]
+[para]
+
+
+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.
+
+[para]
+
+There are a number of options you can specify when defining an option;
+if [const -default] is the only one, you can omit the word 
+[const -default] as follows:
+
+[para]
+[example {snit::type dog {
+    option -breed mongrel
+    option -color brown
+    option -akc   0
+    option -shots 0
+}
+}]
+
+[para]
+
+If no [const -default] value is specified, the option's default value
+will be the empty string (but see [sectref {THE TK OPTION DATABASE}]).
+
+[para]
+
+The Snit man page refers to options like these as "locally defined" options.
+
+[subsection {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 [cmd ::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.
+
+[para]
+[example {% dog spot -breed beagle -color "mottled" -akc 1 -shots 1
+::spot
+% dog fido -shots 1
+::fido
+%
+}]
+[para]
+
+So [cmd ::spot] is a pedigreed beagle; [cmd ::fido] is a typical mutt,
+but his owners evidently take care of him, because he's had his shots.
+
+[para]
+
+[emph Note:] If the type defines a constructor, it can specify a
+different object-creation syntax.  See [sectref CONSTRUCTORS] for more
+information.
+
+[subsection {How can a client retrieve an option's value?}]
+
+Retrieve option values using the [method cget] method:
+
+[para]
+[example {% spot cget -color
+mottled
+% fido cget -breed
+mongrel
+%
+}]
+[para]
+
+[subsection {How can a client set options after object creation?}]
+
+Any number of options may be set at one time using the
+[method 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:
+
+[para]
+[example {% fido configure -color dun -breed "Arctic Boar Hound"
+% fido cget -color
+dun
+% fido cget -breed
+Arctic Boar Hound
+}]
+[para]
+
+Alternatively, the [method configurelist] method takes a list of
+options and values; occasionally this is more convenient:
+
+[para]
+[example {% 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
+%
+}]
+[para]
+
+In Tcl 8.5, the [cmd {*}] keyword can be used with 
+[method configure] in this case:
+
+[para]
+[example {% 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
+%
+}]
+[para]
+
+The results are the same.
+
+[subsection {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 [method configure] and [method cget]
+methods, as shown below.
+
+[para]
+[example {% 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
+%
+}]
+[para]
+
+Alternatively, Snit provides a built-in array instance variable called
+[var options].  The indices are the option names; the values are the
+option values.  The method [method gainWeight] can thus be rewritten as
+follows:
+
+[para]
+[example {
+    method gainWeight {} {
+        incr options(-weight)
+    }
+}]
+[para]
+
+As you can see, using the [var options] variable involves considerably
+less typing and is the usual way to do it.  But if you use 
+[const -configuremethod] or [const -cgetmethod] (described in the following
+answers), you might wish to use the [method configure] and 
+[method 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 [method configure] and [method cget] are the only way
+to access it without accessing the component directly.  See 
+[sectref "DELEGATION"] for more information.
+
+[subsection {How can I make an option read-only?}]
+
+Define the option with [const "-readonly yes"].
+
+[para]
+
+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.  [const -breed] should be read-only, but
+[const -shots] should not be.
+
+[para]
+[example {% 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
+%
+}]
+[para]
+
+[subsection {How can I catch accesses to an option's value?}]
+
+Define a [const -cgetmethod] for the option.
+
+[subsection {What is a -cgetmethod?}]
+
+A [const -cgetmethod] is a method that's called whenever the related
+option's value is queried via the 
+[method 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.
+
+[para]
+
+Here's what the default behavior would look like if
+written using a [const -cgetmethod]:
+
+[para]
+[example {snit::type dog {
+    option -color -default brown -cgetmethod GetOption
+
+    method GetOption {option} {
+        return $options($option)
+    }
+}
+}]
+[para]
+
+Any instance method can be used, provided that it takes one argument,
+the name of the option whose value is to be retrieved.
+
+[subsection {How can I catch changes to an option's value?}]
+
+Define a [const -configuremethod] for the option.
+
+[subsection {What is a -configuremethod?}]
+
+A [const -configuremethod] is a method that's called whenever the
+related option is given a new value via the [method configure] or
+[method 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.
+
+[para]
+
+Here's what the default configuration behavior would look like if
+written using a [const -configuremethod]:
+
+[para]
+[example {snit::type dog {
+    option -color -default brown -configuremethod SetOption
+
+    method SetOption {option value} {
+        set options($option) $value
+    }
+}
+}]
+[para]
+
+Any instance method can be used, provided that it takes two arguments,
+the name of the option and the new value.
+
+[para]
+
+Note that if your method doesn't store the value in the [var options]
+array, the [var options] array won't get updated.
+
+[subsection {How can I validate an option's value?}]
+
+Define a [const -validatemethod].
+
+[subsection {What is a -validatemethod?}]
+
+A [const -validatemethod] is a method that's called whenever the
+related option is given a new value via the [method configure] or
+[method 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 [const -validatemethod], if any, is called
+before the value is stored in the [var options] array; in particular,
+it's called before the [const -configuremethod], if any.
+
+[para]
+
+For example, suppose an option always takes a Boolean value.  You can
+ensure that the value is in fact a valid Boolean like this:
+
+[example {% 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 [const -validatemethod] can be used to validate any number
+of boolean options.
+
+[para]
+
+Any method can be a [const -validatemethod] provided that it takes
+two arguments, the option name and the new option value.
+
+
+[section {TYPE VARIABLES}]
+
+[subsection {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 [term "static member variable"] is used for the same notion.
+Type variables can be scalars or arrays.
+
+
+[subsection {How is a scalar type variable defined?}]
+
+Scalar type variables are defined in the type definition using the
+[cmd typevariable] statement.  You can simply name it, or you can
+initialize it with a value:
+
+[para]
+[example {
+snit::type mytype {
+    # Define variable "greeting" and initialize it with "Howdy!"
+    typevariable greeting "Howdy!"
+}
+}]
+[para]
+
+Every object of type [cmd mytype] now has access to a single variable
+called [var greeting].
+
+[subsection {How is an array-valued type variable defined?}]
+
+Array-valued type variables are also defined using the
+[cmd typevariable] command; to initialize them, include the 
+[const -array] option:
+
+[para]
+[example {snit::type mytype {
+    # Define typearray variable "greetings"
+    typevariable greetings -array {
+        formal "Good Evening"
+        casual "Howdy!"
+    }
+}
+}]
+[para]
+
+[subsection {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.
+
+[subsection {Are there any limitations on type variable names?}]
+
+Type variable names have the same restrictions as 
+the names of [sectref {INSTANCE VARIABLES}] do.
+
+[subsection {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 [sectref {INSTANCE METHODS}] or [sectref {TYPE METHODS}] without
+declaration.  This differs from normal Tcl practice, in which all
+non-local variables in a proc need to be declared.
+
+[para]
+
+Type variables are subject to the same speed/readability tradeoffs
+as instance variables; see
+[sectref {Do I need to declare my instance variables in my methods?}] 
+
+[subsection {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 [option -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.
+
+[para]
+
+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 [cmd mytypevar] command:
+
+[para] 
+[example {snit::widget mywidget {
+    typevariable labeltext ""
+
+    constructor {args} {
+        # ...
+
+        label $win.label -textvariable [mytypevar labeltext]
+
+        # ...
+    }
+}
+}]
+[para]
+
+[subsection {How do I make a type variable public?}]
+
+There are two ways to do this.  The preferred way is to write a pair
+of [sectref {TYPE METHODS}] to set and query the type variable's value.
+
+[para]
+
+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,
+
+[para]
+[example {snit::type mytype {
+    typevariable myvariable
+}
+
+set ::mytype::myvariable "New Value"
+}]
+[para]
+
+[section {TYPE METHODS}]
+
+[subsection {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.
+
+[subsection {How do I define a type method?}]
+
+Type methods are defined in the type definition using the
+
+[cmd typemethod] statement:
+
+[para]
+[example {snit::type dog {
+    # List of pedigreed dogs
+    typevariable pedigreed
+
+    typemethod pedigreedDogs {} {
+        return $pedigreed
+    }
+}
+}]
+[para]
+
+Suppose the [cmd dog] type maintains a list of the names of the dogs
+that have pedigrees.  The [cmd pedigreedDogs] type method returns this
+list.
+
+[para]
+
+The [cmd typemethod] statement looks just like a normal Tcl
+[cmd proc], except that it appears in a [cmd snit::type] definition.
+Notice that every type method gets an implicit argument called
+[var type], which contains the fully-qualified type name.
+
+[subsection {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 [var pedigreedDogs],
+
+[para]
+[example {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] { ... }
+}]
+[para]
+
+[subsection {Are there any limitations on type method names?}]
+
+Not really, so long as you avoid the standard type method names:
+[method create], [method destroy], and [method info].
+
+
+[subsection {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.
+
+[para]
+
+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.
+
+[para]
+
+Alternatively, a Snit [cmd proc] can be used as a private type method; see
+[sectref PROCS].
+
+
+[subsection {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 [var args] argument.
+
+[para]
+
+However, every type method is called with an implicit argument called
+[var 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 [sectref {INSTANCE METHODS}].
+
+[subsection {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 [var \$type] to do so:
+
+[para]
+[example {snit::type dog {
+
+    typemethod pedigreedDogs {} { ... }
+
+    typemethod printPedigrees {} {
+        foreach obj [$type pedigreedDogs] { ... }
+    }
+}
+}]
+[para]
+
+[subsection {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, [var type].  For example, suppose we want to print a
+list of pedigreed dogs when a Tk button is pushed:
+
+[para]
+[example {
+button .btn -text "Pedigrees" -command [list dog printPedigrees]
+pack .btn
+}]
+
+Alternatively, from a method or type method you can use the 
+[cmd mytypemethod] command, just as you would use [cmd mymethod]
+to define a callback command for [sectref {INSTANCE METHODS}].
+
+[subsection {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
+[sectref {INSTANCE METHODS}] for more.
+
+[section PROCS]
+
+[subsection {What is a proc?}]
+
+A Snit [cmd 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. 
+
+[subsection {How do I define a proc?}]
+
+Procs are defined by including a [cmd proc] statement in the type
+definition:
+
+[para]
+[example {snit::type mytype {
+    # Pops and returns the first item from the list stored in the
+    # listvar, updating the listvar
+   proc pop {listvar} { ... }
+
+   # ...
+}
+}]
+[para]
+
+[subsection {Are there any limitations on proc names?}]
+
+Any name can be used, so long as it does not begin with [const Snit_];
+names beginning with [const Snit_] are reserved for Snit's own use.
+However, the wise programmer will avoid [cmd proc] names ([cmd set],
+[cmd list], [cmd if], etc.) that would shadow standard Tcl
+command names.
+
+[para]
+
+[cmd proc] names, being private, should begin with a capital letter according
+to convention; however, as there are typically no public [cmd proc]s
+in the type's namespace it doesn't matter much either way.
+
+[subsection {How does a method call a proc?}]
+
+Just like it calls any Tcl command.  For example,
+
+[para]
+
+[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]
+    }
+}
+}]
+[para]
+
+[subsection {How can I pass a proc to another object as a callback?}]
+
+The [cmd myproc] command returns a callback command for the 
+[cmd proc], just as [cmd mymethod] does for a method.
+
+[section {TYPE CONSTRUCTORS}]
+
+[subsection {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.
+
+[para]
+
+A type can have at most one type constructor.
+
+
+[subsection {How do I define a type constructor?}]
+
+A type constructor is defined by using the [cmd 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.
+
+[para]
+[example {% snit::type mytype {
+    typevariable lookupTable
+
+    typeconstructor {
+        array set lookupTable {key value...}
+    }
+}
+}]
+[para]
+
+
+
+[section CONSTRUCTORS]
+
+[subsection {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 [cmd snit::type] command's
+[method 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.
+
+[para]
+
+The constructor's return value is ignored (unless it's an
+error, of course).
+
+
+[subsection {How do I define a constructor?}]
+
+A constructor is defined by using the [cmd 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.
+
+[para] 
+[example {% 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
+%
+}]
+[para]
+
+[subsection {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:
+
+[para]
+[example {snit::type dog {
+    constructor {args} {
+        $self configurelist $args
+    }
+}
+}]
+[para]
+
+When the constructor is called, [var 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 [method configurelist] method, as shown.
+
+[subsection {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:
+
+[para]
+[example {% 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
+}]
+[para]
+
+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 
+[sectref COMPONENTS] using the standard creation syntax.
+
+[subsection {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 
+[var args] argument.
+
+[subsection "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
+[cmd snit::widget]s and [cmd snit::widgetadaptor]s.  See 
+[sectref {DELEGATION}], [sectref {WIDGETS}], 
+[sectref {WIDGET ADAPTORS}], and [sectref {THE TK OPTION DATABASE}].
+
+[section DESTRUCTORS]
+
+[subsection {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 [sectref COMPONENTS], closing files,
+and so forth.
+
+[subsection {How do I define a destructor?}]
+
+Destructors are defined by using the [cmd destructor] statement in the
+type definition.
+
+[para]
+Suppose we're maintaining a list of pedigreed dogs;
+then we'll want to remove dogs from it when they are destroyed.
+
+[para]
+[example {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
+    }
+}
+}]
+[para]
+
+[subsection {Are there any limitations on destructor arguments?}]
+
+Yes; a destructor has no explicit arguments.
+
+[subsection {What implicit arguments are passed to the destructor?}]
+
+The destructor gets the same implicit arguments that are passed to
+[sectref {INSTANCE METHODS}]: [var type], [var selfns], [var win], and
+[var self].
+
+[subsection {Must components be destroyed explicitly?}]
+
+Yes and no.
+
+[para]
+
+Any Tk widgets created by a [cmd snit::widget] or
+[cmd 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).
+
+[para]
+
+Components of normal [cmd 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.
+
+[subsection {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.  
+
+[para]
+
+For example, a [cmd dog] might create a [cmd 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 [cmd tail] to destroy.  The simplest solution is
+generally to catch and ignore any errors while destroying components.
+
+[example {snit::type dog {
+    component tail
+
+    constructor {args} {
+        $self configurelist $args
+
+        set tail [tail %AUTO%]
+    }
+
+    destructor {
+        catch {$tail destroy}
+    }
+}
+}]
+
+
+[section COMPONENTS]
+
+[subsection {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.
+
+[para]
+
+But Snit also has a more precise meaning for 
+[sectref COMPONENTS COMPONENT].  The components of a Snit object are those
+objects to which methods or options can be delegated.
+(See [sectref DELEGATION] for more information about delegation.)
+
+[subsection {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 [cmd component] statement.  The [cmd component]
+statement declares an [term {instance variable}] which is used to
+store the component's command name when the component is created.
+
+[para]
+
+For example, suppose your [cmd dog] object
+creates a [cmd tail] object (the better to wag with, no doubt):
+
+[para]
+[example {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
+    }
+}
+}]
+[para]
+
+As shown here, it doesn't matter what the [cmd tail] object's real
+name is; the [cmd dog] object refers to it by its component name.
+
+[para]
+
+The above example shows one way to delegate the [method wag] method to
+the [var mytail] component; see [sectref DELEGATION] for an easier way.
+
+[subsection {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.
+
+[para]
+
+In the example in the previous question, the component name is 
+[const mytail]; the [const mytail] component's object name is chosen
+automatically by Snit since [const %AUTO%] was used when the component
+object was created.
+
+[subsection {Are there any limitations on component names?}]
+
+Yes.  [cmd snit::widget] and [cmd snit::widgetadaptor] objects have a special
+component called the [var hull] component; thus, the name [var hull]
+should be used for no other purpose.
+
+[para]
+
+Otherwise, since component names are in fact instance variable names
+they must follow the rules for [sectref {INSTANCE VARIABLES}].
+
+[subsection {What is an owned component?}]
+
+An [term owned] component is a component whose object command's
+lifetime is controlled by the [cmd snit::type] or [cmd snit::widget].
+
+[para]
+
+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:
+
+[example {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.
+
+[subsection {What does the install command do?}]
+
+The [cmd install] command creates an owned component using a specified
+command, and assigns the result to the component's instance variable.
+For example:
+
+[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 [cmd snit::type]'s code, the [cmd install]
+command shown above is equivalent to the [const {set mytail}] command
+that's commented out.  In a [cmd snit::widget]'s or 
+[cmd snit::widgetadaptor]'s, code, however, the
+[cmd install] command also queries [sectref {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 [cmd install] for all
+owned components.
+
+[subsection {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.
+
+[subsection {Are there any limitations on component object names?}]
+
+Yes.
+
+[para]
+
+Component objects which are Tk widgets or megawidgets must have valid
+Tk window names.
+
+[para]
+
+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.
+
+[para]
+
+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:
+
+[para]
+[example {snit::type tail { ... }
+
+snit::type dog {
+    delegate method wag to mytail
+
+    constructor {} {
+        install mytail using tail mytail
+    }
+}
+}]
+[para]
+
+This code uses the component name, [const "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 [const mytail] component is
+created in the [const ::dog::] namespace, and will thus have the name
+[cmd ::dog::mytail].
+
+[para]
+
+Now, suppose you create two dogs.  Both dogs will attempt to
+create a tail called [cmd ::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:
+
+[para]
+
+First, if the component type is a [cmd snit::type] you can
+specify [const %AUTO%] as its name, and be guaranteed to get a unique name.
+This is the safest thing to do:
+
+[para]
+[example {
+    install mytail using tail %AUTO%
+}]
+[para]
+
+If the component type isn't a [cmd snit::type] you can create
+the component in the object's instance namespace:
+
+[para]
+[example {
+    install mytail using tail ${selfns}::mytail
+}]
+[para]
+
+Make sure you pick a unique name within the instance namespace.
+
+[subsection {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 [cmd snit::widget]
+or [cmd snit::widgetadaptor] you don't need to destroy any components
+that are widgets, because they will generally be children or
+descendants of your megawidget.
+
+[para]
+
+If your object is an instance of [cmd snit::type], though, none of its
+owned components will be destroyed automatically, nor will be
+non-widget components of a [cmd snit::widget] be destroyed
+automatically.  All such owned components must be destroyed
+explicitly, or they won't be destroyed at all.
+
+[subsection {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 [sectref 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.
+
+[para]
+
+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.
+
+
+[subsection {How do I expose a component's object command?}]
+
+When you declare the component, specify the [cmd component]
+statement's [const -public] option.  The value of this option is the
+name of a method which will be delegated to your component's object 
+command.
+
+[para]
+
+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:
+
+[para]
+[example {snit::widget combobox {
+     component listbox -public listbox
+
+     constructor {args} {
+         install listbox using listbox $win.listbox ....
+     }
+}
+
+combobox .mycombo
+.mycombo listbox configure -width 30
+}]
+[para]
+
+Your comobox widget, [cmd .mycombo], now has a [method 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.
+
+[para]
+
+Usually you'll let the method name be the same as the component name;
+however, you can name it anything you like.
+
+[section {TYPE COMPONENTS}]
+
+[subsection {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 [sectref {INSTANCE VARIABLES}] and 
+[sectref {TYPE VARIABLES}].  Both [sectref {INSTANCE METHODS}] and
+[sectref {TYPE METHODS}] can be delegated to type components.
+
+[para]
+
+Once you understand [sectref COMPONENTS] and
+[sectref {DELEGATION}], type components are just more of the same.
+
+[subsection {How do I declare a type component?}]
+
+Declare a type component using the [cmd typecomponent] statement.  It
+takes the same options ([const -inherit] and [const -public]) as the
+[cmd component] statement does, and defines a type variable to hold
+the type component's object command.
+
+[para]
+
+Suppose in your model you've got many dogs, but only one
+veterinarian.  You might make the veterinarian a type component.
+
+[example {snit::type veterinarian { ... }
+
+snit::type dog {
+    typecomponent vet
+
+    # ...
+}
+}]
+
+[subsection {How do I install a type component?}]
+
+Just use the [cmd set] command to assign the component's object
+command to the type component.  Because types 
+(even [cmd snit::widget] types) are not widgets, and do not have
+options anyway, the extra features of the [cmd install] command are
+not needed.
+
+[para]
+
+You'll usually install type components in the type constructor, as
+shown here:
+
+[example {snit::type veterinarian { ... }
+
+snit::type dog {
+    typecomponent vet
+
+    typeconstructor {
+        set vet [veterinarian %AUTO%]
+    }
+}
+}]
+
+[subsection {Are there any limitations on type component names?}]
+
+Yes, the same as on [sectref {INSTANCE VARIABLES}], 
+[sectref {TYPE VARIABLES}], and normal [sectref COMPONENTS].
+
+
+[section DELEGATION]
+
+[subsection {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 [cmd dog] object can delegate its [cmd wag] method and its
+[option -taillength] option to its [cmd tail] component.
+
+[para] 
+[example {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
+    }
+
+}
+}]
+[para]
+
+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.
+
+[para]
+
+Note that the constructor calls the [method configurelist] method
+[cmd after] it creates its [cmd tail]; otherwise,
+if [option -taillength] appeared in the list of [var args] we'd get an
+error.
+
+[subsection {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 [cmd delegate] statement in the type definition.
+
+(See [sectref COMPONENTS] and [sectref {TYPE COMPONENTS}]
+for more information about component names.)
+
+[para]
+
+For example, here's a much better way to delegate the [cmd dog]
+object's [cmd wag] method:
+
+[para]
+[example {% 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.
+}]
+[para]
+
+This code has the same effect as the code shown under the previous
+question: when a [cmd dog]'s [cmd wag] method is called, the call and
+its arguments are passed along automatically to the [cmd tail] object.
+
+[para]
+
+Note that when a component is mentioned in a [cmd delegate] statement,
+the component's instance variable is defined implicitly.  However,
+it's still good practice to declare it explicitly using the
+[cmd component] statement.
+
+[para]
+
+Note also that you can define a method name using the [cmd method]
+statement, or you can define it using [cmd delegate]; you can't do
+both.
+
+[subsection {Can I delegate to a method with a different name?}]
+
+Suppose you wanted to delegate the [cmd dog]'s [method wagtail] method to
+the [cmd tail]'s [method wag] method.  After all you wag the tail, not
+the dog.  It's easily done:
+
+[para]
+[example {snit::type dog {
+    delegate method wagtail to mytail as wag
+
+    constructor {args} {
+        install mytail using tail %AUTO% -partof $self
+        $self configurelist $args
+    }
+}
+}]
+[para]
+
+
+[subsection {Can I delegate to a method with additional arguments?}]
+
+Suppose the [cmd tail]'s [method wag] method takes as an argument the
+number of times the tail should be wagged.  You want to delegate the
+[cmd dog]'s [method wagtail] method to the [cmd tail]'s [method wag]
+method, specifying that the tail should be wagged exactly three times.
+This is easily done, too:
+
+[para]
+[example {snit::type dog {
+    delegate method wagtail to mytail as {wag 3}
+    # ...
+}
+
+snit::type tail {
+    method wag {count} {
+        return [string repeat "Wag " $count]
+    }
+    # ...
+}
+}]
+[para]
+
+[subsection {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 [cmd delegate] statement's [const using] clause.
+
+[para]
+
+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, [cmd saverec]
+saves a record.  If you let the record ID be the name of the dog
+object, you can delegate the dog's [method save] method to the 
+[cmd saverec] command as follows:
+
+[example {snit::type dog {
+    delegate method save using {saverec %s}
+}
+}]
+
+The [const %s] is replaced with the instance name when the 
+[method save] method is called; any additional arguments are the
+appended to the resulting command.
+
+[para]
+
+The [const using] clause understands a number of other %-conversions;
+in addition to the instance name, you can substitute in the method 
+name ([const %m]), the type name ([const %t]), the instance 
+namespace ([const %n]), the Tk window name ([const %w]), and,
+if a component or typecomponent name was given in the 
+[cmd delegate] statement, the component's object command 
+([const %c]).
+
+[subsection {How can I delegate a method to a type component object?}]
+
+Just exactly as you would to a component object.  The 
+[cmd {delegate method}] statement accepts both component and type
+component names in its [const to] clause.
+
+[subsection {How can I delegate a type method to a type component object?}]
+
+Use the [cmd {delegate typemethod}] statement.  It works like
+[cmd {delegate method}], with these differences: first, it defines
+a type method instead of an instance method; second, the 
+[const using] clause ignores the [const {%s}], [const {%n}], 
+and [const {%w}] %-conversions.
+
+[para]
+
+Naturally, you can't delegate a type method to an instance
+component...Snit wouldn't know which instance should receive it.
+
+[subsection {How can I delegate an option to a component object?}]
+
+The first question in this section (see [sectref 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 [cmd tail]
+object has a [option -length] option; we want to allow the creator of
+a [cmd dog] object to set the tail's length.  We can do this:
+
+[para]
+[example {% 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
+}]
+[para]
+
+This produces nearly the same result as the [const -configuremethod] and
+[const -cgetmethod] shown under the first question in this
+section: whenever a [cmd dog] object's [option -length] option is set
+or retrieved, the underlying [cmd tail] object's option is set or
+retrieved in turn.
+
+[para]
+
+Note that you can define an option name using the [cmd option]
+statement, or you can define it using [cmd delegate]; you can't do
+both.
+
+[subsection {Can I delegate to an option with a different name?}]
+
+In the previous answer we delegated the [cmd dog]'s [option -length]
+option down to its [cmd 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 [cmd dog] a [option -taillength]
+option, but delegate it to the [cmd tail]'s [option -length] option:
+
+[para]
+[example {snit::type dog {
+    delegate option -taillength to mytail as -length
+
+    constructor {args} {
+        set mytail [tail %AUTO% -partof $self]
+        $self configurelist $args
+    }
+}
+}]
+[para]
+
+[subsection {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 [cmd snit::widgetadaptors],
+for example, where we wish to slightly the modify the behavior of an
+existing widget.  To carry on with our [cmd dog] example, however, suppose
+that we have a [cmd snit::type] called [cmd animal] that implements a
+variety of animal behaviors--moving, eating, sleeping, and so forth.
+
+We want our [cmd dog] objects to inherit these same behaviors, while
+adding dog-like behaviors of its own.
+
+Here's how we can give a [cmd dog] methods and options of its own
+while delegating all other methods and options to its [cmd animal]
+component:
+
+[para]
+[example {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"
+    }
+}
+}]
+[para]
+
+That's it.  A [cmd dog] is now an [cmd animal] that has a
+[option -akc] option and can [cmd wag] its tail.
+
+[para]
+
+Note that we don't need to specify the full list of method names or
+option names that [cmd animal] will receive.
+It gets anything [cmd dog] doesn't recognize--and if it doesn't
+recognize it either, it will simply throw an error, just as it should.
+
+[para]
+
+You can also delegate all unknown type methods to a type component
+using [cmd {delegate typemethod *}].
+
+[subsection {How can I delegate all but certain methods or options to a component?}]
+
+In the previous answer, we said that every [cmd dog] is
+an [cmd animal] by delegating all unknown methods and options to the
+[var animal] component. But what if the [cmd animal] type has some
+methods or options that we'd like to suppress?
+
+[para]
+
+One solution is to explicitly delegate all the options and methods,
+and forgo the convenience of [cmd {delegate method *}] and
+[cmd {delegate option *}].  But if we wish to suppress only a few
+options or methods, there's an easier way:
+
+[para]
+[example {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
+    }
+
+    # ...
+}
+}]
+[para]
+
+Dogs have four legs, so we specify that explicitly when we create the
+[var animal] component, and explicitly exclude [option -numlegs] from the
+set of delegated options.  Similarly, dogs can neither 
+[method fly] nor [method climb],
+so we exclude those [cmd animal] methods as shown.
+
+[subsection {Can a hierarchical method be delegated?}]
+
+Yes; just specify multiple words in the delegated method's name:
+
+[para]
+[example {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
+    }
+
+    # ...
+}
+}]
+[para]
+
+Unrecognized hierarchical methods can also be delegated; the following
+code delegates all subcommands of the "tail" method to the "mytail"
+component:
+
+[para]
+[example {snit::type dog {
+    delegate method {tail *} to mytail
+
+    # ...
+}
+}]
+[para]
+
+
+
+
+[section WIDGETS]
+
+[subsection {What is a snit::widget?}]
+
+A [cmd snit::widget] is the Snit version of what Tcl programmers
+usually call a [term megawidget]: a widget-like object usually
+consisting of one or more Tk widgets all contained within a Tk frame.
+
+[para]
+
+A [cmd snit::widget] is also a special kind of [cmd snit::type].  Just
+about everything in this FAQ list that relates to [cmd snit::types]
+also applies to [cmd snit::widgets].
+
+
+[subsection {How do I define a snit::widget?}]
+
+[cmd snit::widgets] are defined using the [cmd snit::widget] command,
+just as [cmd snit::types] are defined by the [cmd snit::type] command.
+
+[para]
+
+The body of the definition can contain all of the same kinds of
+statements, plus a couple of others which will be mentioned below.
+
+
+[subsection {How do snit::widgets differ from snit::types?}]
+
+[list_begin itemized]
+[item]
+
+The name of an instance of a [cmd snit::type] can be any valid Tcl
+command name, in any namespace.
+
+The name of an instance of a [cmd snit::widget] must be a valid Tk
+widget name, and its parent widget must already exist.
+
+
+[item]
+
+An instance of a [cmd snit::type] can be destroyed by calling
+
+its [cmd destroy] method.  Instances of a [cmd snit::widget] have no
+destroy method; use the Tk [cmd destroy] command instead.
+
+
+[item]
+
+Every instance of a [cmd snit::widget] has one predefined component
+called its [var hull] component.
+
+The hull is usually a Tk [cmd frame] or [cmd toplevel] widget; any other
+widgets created as part of the [cmd snit::widget] will usually be
+contained within the hull.
+
+[item]
+
+[cmd snit::widget]s can have their options receive default values from
+[sectref {THE TK OPTION DATABASE}].
+
+[list_end]
+
+[subsection {What is a hull component?}]
+
+Snit can't create a Tk widget object; only Tk can do that.
+
+Thus, every instance of a [cmd snit::widget] must be wrapped around a
+genuine Tk widget; this Tk widget is called the [term {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.
+
+[para]
+
+For [cmd snit::widget]s the hull component must be a Tk widget that
+defines the [const -class] option.
+
+[para]
+
+[cmd snit::widgetadaptor]s differ from [cmd snit::widget]s chiefly in
+that any kind of widget can be used as the hull component; see
+[sectref {WIDGET ADAPTORS}].
+
+[subsection {How can I set the hull type for a snit::widget?}]
+
+A [cmd snit::widget]'s hull component will usually be a Tk [cmd frame]
+widget; however, it may be any Tk widget that defines the 
+[const -class] option.  You can
+explicitly choose the hull type you prefer by including the [cmd hulltype]
+command in the widget definition:
+
+[para]
+[example {snit::widget mytoplevel {
+    hulltype toplevel
+
+    # ...
+}
+}]
+[para]
+
+If no [cmd hulltype] command appears, the hull will be a [cmd frame].
+
+[para]
+
+By default, Snit recognizes the following hull types: the Tk widgets
+[cmd frame], [cmd labelframe], [cmd toplevel], and the Tile widgets
+[cmd ttk::frame], [cmd ttk::labelframe], and [cmd ttk::toplevel].  To
+enable the use of some other kind of widget as the hull type, you can
+[cmd lappend] the widget command to the variable [var snit::hulltypes] (always
+provided the widget defines the [const -class] option.  For example,
+suppose Tk gets a new widget type called a [cmd prettyframe]:
+
+[para]
+[example {lappend snit::hulltypes prettyframe
+
+snit::widget mywidget {
+    hulltype prettyframe
+
+    # ...
+}
+}]
+[para]
+
+
+
+[subsection {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 [cmd snit::widget] is first
+created, its instance name, [var self], is a Tk window name;
+
+however, if the [cmd snit::widget] is used as the hull component by a
+[cmd snit::widgetadaptor] its instance name will be changed to
+something else.  For this reason, every [cmd snit::widget] method,
+constructor, destructor, and so forth is passed another implicit
+argument, [var win], which is the window name of the megawidget.  Any
+children should be named using [var win] as the root.
+
+[para]
+
+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:
+
+[para]
+[example {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
+
+    }
+}
+}]
+[para]
+
+See also the question on renaming objects, toward the top of this
+file.
+
+[section {WIDGET ADAPTORS}]
+
+[subsection {What is a snit::widgetadaptor?}]
+
+A [cmd snit::widgetadaptor] is a kind of [cmd snit::widget].  Whereas
+a [cmd snit::widget]'s hull is automatically created and is always a
+Tk frame, a [cmd 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.
+
+[para]
+
+It's called a [term {widget adaptor}] because it allows you to take an
+existing widget and customize its behavior.
+
+
+[subsection {How do I define a snit::widgetadaptor?}]
+
+Use the [cmd snit::widgetadaptor] command.  The definition for a
+[cmd snit::widgetadaptor] looks just like that for a [cmd snit::type]
+or [cmd snit::widget], except that the constructor must create and
+install the hull component.
+
+[para]
+
+For example, the following code creates a read-only text widget by the
+simple device of turning its [method insert] and [method delete]
+methods into no-ops.  Then, we define new methods, [method ins] and
+[method del],
+
+which get delegated to the hull component as [method insert] and
+[method delete].  Thus, we've adapted the text widget and given it new
+behavior while still leaving it fundamentally a text widget.
+
+[para]
+[example {::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
+}
+}]
+[para]
+
+The most important part is in the constructor.
+Whereas [cmd snit::widget] creates the hull for you,
+[cmd 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 [cmd installhull] command.
+
+[para]
+
+[emph Note:] There is no instance command until you create one by
+installing a hull component.  Any attempt to pass methods to [var \$self]
+prior to calling [cmd installhull] will fail.
+
+[subsection {Can I adapt a widget created elsewhere in the program?}]
+
+Yes.
+
+[para]
+
+At times, it can be convenient to adapt a pre-existing widget instead
+of creating your own.
+For example, the Bwidget [cmd PagesManager] widget manages a
+set of [cmd frame] widgets, only one of which is visible at a time.
+The application chooses which [cmd frame] is visible.  All of the
+These [cmd frame]s are created by the [cmd PagesManager] itself, using
+its [method add] method.  It's convenient to adapt these frames to
+do what we'd like them to do.
+
+[para]
+
+In a case like this, the Tk widget will already exist when the
+[cmd snit::widgetadaptor] is created.  Snit provides an alternate form
+of the [cmd installhull] command for this purpose:
+
+[para]
+[example {snit::widgetadaptor pageadaptor {
+    constructor {args} {
+        # The widget already exists; just install it.
+        installhull $win
+
+        # ...
+    }
+}
+}]
+
+[subsection {Can I adapt another megawidget?}]
+
+Maybe. If the other megawidget is a [cmd snit::widget] or
+[cmd 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 [const <Destroy>] event before the
+megawidget you're adapting does.
+
+[section {THE TK OPTION DATABASE}]
+
+[subsection {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).
+
+[para]
+
+Full details about the Tk option database are beyond the scope of this
+document; both [emph {Practical Programming in Tcl and Tk}] by Welch,
+Jones, and Hobbs, and [emph {Effective Tcl/Tk Programming}] by
+Harrison and McClennan., have good introductions to it.
+
+[para]
+
+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.
+
+[para]
+
+[list_begin itemized]
+
+[item]
+
+If the widget's default widget class is not what is desired, set it
+explicitly using the [cmd widgetclass] statement in the widget
+definition.
+
+[item]
+
+When defining or delegating options, specify the resource and class
+names explicitly when necessary.
+
+[item]
+
+Use the [cmd {installhull using}] command to create and install the
+hull for [cmd snit::widgetadaptor]s.
+
+[item]
+
+Use the [cmd install] command to create and install all
+components which are widgets.
+
+[item]
+
+Use the [cmd install] command to create and install 
+components which aren't widgets if you'd like them to 
+receive option values from the option database.
+
+[list_end]
+[para]
+
+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.
+
+
+[subsection {Do snit::types use the Tk option database?}]
+
+No, they don't; querying the option database requires a Tk window
+name, and [cmd snit::type]s don't have one.
+
+[para]
+
+If you create an instance of a [cmd snit::type] as a
+component of a [cmd snit::widget] or [cmd snit::widgetadaptor], on the
+other hand, and if any options are delegated to the component,
+and if you use [cmd install] to create and install it, then
+the megawidget will query the option database on the
+[cmd snit::type]'s behalf.  This might or might not be what you
+want, so take care.
+
+[subsection {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 [cmd button] widget is 
+[const Button].
+
+[para]
+
+Similarly, the widget class of a [cmd snit::widget] defaults to the
+unqualified type name with the first letter capitalized.  For example,
+the widget class of
+
+[para]
+[example {snit::widget ::mylibrary::scrolledText { ... }
+}]
+[para]
+
+is [const ScrolledText].
+
+[para]
+
+The widget class can also be set explicitly using the
+[cmd widgetclass] statement within the [cmd snit::widget] definition:
+
+[para]
+[example {snit::widget ::mylibrary::scrolledText {
+    widgetclass Text
+
+    # ...
+}
+}]
+[para]
+
+The above definition says that a [cmd scrolledText] megawidget has the
+same widget class as an ordinary [cmd 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.
+
+[subsection {What is my snit::widgetadaptor's widget class?}]
+
+The widget class of a [cmd snit::widgetadaptor] is just the widget
+class of its hull widget; Snit has no control over this.
+
+[para]
+
+Note that the widget class can be changed only for [cmd frame] and
+[cmd toplevel] widgets, which is why these are the valid hull types
+for [cmd snit::widget]s.
+
+[para]
+
+Try to use [cmd snit::widgetadaptor]s 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.
+
+
+[subsection {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 [cmd configure] and [cmd cget]
+commands.
+
+[para]
+
+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 [cmd text]
+widget options:
+
+[para]
+[example {    -background         background         Background 
+    -borderwidth        borderWidth        BorderWidth 
+    -insertborderwidth  insertBorderWidth  BorderWidth 
+    -padx               padX               Pad 
+}]
+[para]
+
+As is easily seen, sometimes the resource and class names can be
+inferred from the option name, but not always.
+
+
+[subsection {What are the resource and class names for my megawidget's options?}]
+
+For options implicitly delegated to a component using
+[cmd {delegate option *}], the resource and class names will be
+exactly those defined by the component.  The [cmd configure] method
+returns these names, along with the option's default and current
+values:
+
+[para]
+[example {% 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
+%
+}]
+[para]
+
+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.
+
+[para]
+
+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":
+
+[para]
+[example {% 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
+%
+}]
+[para]
+
+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:
+
+[para]
+[example {% snit::widget mytext {
+    delegate option {-padx padX Pad} to text
+
+    # ...
+}
+::mytext
+% mytext .text
+.text
+% .text configure -padx
+-padx padX Pad 1 1
+%
+}]
+
+
+[subsection {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,
+
+[para]
+[example {option add *Mywidget.texture pebbled
+
+snit::widget mywidget {
+    option -texture smooth
+    # ...
+}
+
+mywidget .mywidget -texture greasy
+}]
+[para]
+
+Here, [const -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".
+
+[subsection {How does Snit initialize delegated options?}]
+
+That depends on whether the options are delegated to the hull, or to
+some other component.
+
+
+[subsection {How does Snit initialize options delegated to the hull?}]
+
+A [cmd 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:
+
+[para]
+[example {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]
+}]
+[para]
+
+The question is, what are the values of variables A, B, C and D?
+
+[para]
+
+The value of A is "sunken".  The hull is a Tk frame which has been
+given the widget class [const Mywidget]; it will automatically query the
+option database and pick up this value.  Since the [const -relief] option is
+implicitly delegated to the hull, Snit takes no action.
+
+[para]
+
+The value of B is "red".  The hull will automatically pick up the
+value "green" for its [const -background] option, just as it picked up the
+[const -relief] value.  However, Snit knows that [const -hullbackground]
+is mapped to the hull's [const -background] option; hence, it queries 
+the option database for [const -hullbackground] and gets "red" and 
+updates the hull accordingly.
+
+[para]
+
+The value of C is also "red", because [const -background] is implicitly
+delegated to the hull; thus, retrieving it is the same as retrieving
+[const -hullbackground].  Note that this case is unusual; the 
+[const -background] option should probably have been excluded using the delegate
+statement's [const except] clause, or (more likely) delegated to some other
+component.
+
+[para]
+
+The value of D is "5", but not for the reason you think.  Note that as
+it is defined above, the resource name for [const -borderwidth] defaults to
+[const borderwidth], whereas the option database entry is 
+[const borderWidth], in
+accordance with the standard Tk naming for this option.  As with
+[const -relief], the hull picks up its own [const -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 
+[const -borderwidth] option
+should have been delegated like this:
+
+[para]
+[example {    delegate option {-borderwidth borderWidth BorderWidth} to hull
+}]
+[para]
+
+For [cmd snit::widgetadaptor]s, 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 [cmd snit::widgetadaptor]
+must call [cmd installhull] in its constructor.  The normal way
+to do this is as follows:
+
+[para]
+[example {snit::widgetadaptor mywidget {
+    # ...
+    constructor {args} {
+        # ...
+        installhull using text -foreground white
+        # ...
+    }
+    # ...
+}
+}]
+[para]
+
+In this case, the [cmd installhull] command will create the hull using
+a command like this:
+
+[para]
+[example {    set hull [text $win -foreground white]
+}]
+[para]
+
+The hull is a [cmd text] widget, so its widget class is [const Text].  Just
+as with [cmd 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.
+
+[para]
+
+In earlier versions of Snit, [cmd snit::widgetadaptor]s were expected
+to call [cmd installhull] like this:
+
+[para]
+[example {    installhull [text $win -foreground white]
+}]
+[para]
+
+This form still works--but Snit will not query the option database as
+described above.
+
+[subsection {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.
+
+[para]
+
+A component widget remains a widget still, and is therefore
+initialized from the option database in the usual way.  A [cmd text]
+widget remains a [cmd text] widget whether it is a component of a
+megawidget or not, and will be created as such.
+
+[para]
+
+But then, the option database is queried for all options delegated to
+the component, and the component is initialized accordingly--provided
+that the [cmd install] command is used to create it.
+
+[para]
+
+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:
+
+[para]
+[example {snit::widget mywidget {
+    delegate option -background to myComp
+
+    constructor {args} {
+        set myComp [text $win.text -foreground black]
+    }
+}
+}]
+[para]
+
+The drawback of this method is that Snit has no opportunity to
+initialize the component properly.  Hence, the following approach is
+now used:
+
+[para]
+[example {snit::widget mywidget {
+    delegate option -background to myComp
+
+    constructor {args} {
+        install myComp using text $win.text -foreground black
+    }
+}
+}]
+[para]
+
+The [cmd install] command does the following:
+
+[para]
+[list_begin itemized]
+
+[item]
+
+Builds a list of the options explicitly included in the [cmd install]
+command--in this case, [const -foreground].
+
+[item]
+
+Queries the option database for all options delegated explicitly to
+the named component.
+
+[item]
+
+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 [const -foreground]) will 
+override anything read from the option database.
+
+[item]
+
+If the widget definition implicitly delegated options to the component
+using [cmd {delegate option *}], then Snit calls the newly created
+component's [cmd 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 [cmd install] command.  For all such options, Snit
+queries the option database and configures the component accordingly.
+
+[list_end]
+
+You don't really need to know all of this; just use [cmd install] to
+install your components, and Snit will try to do the right thing.
+
+[subsection {What happens if I install a non-widget as a component of widget?}]
+
+A [cmd snit::type] never queries the option database.
+However, a [cmd snit::widget] can have non-widget components.  And if
+options are delegated to those components, and if the [cmd install]
+command is used to install those components, then they will be
+initialized from the option database just as widget components are.
+
+[para]
+
+However, when used within a megawidget, [cmd install] assumes that the
+created component uses a reasonably standard widget-like creation
+syntax.  If it doesn't, don't use [cmd install].
+
+[section {ENSEMBLE COMMANDS}]
+
+[subsection {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 [cmd string], [cmd file], 
+and [cmd clock].  In a sense, these are singleton objects--there's
+only one instance of them.
+
+[subsection {How can I create an ensemble command using Snit?}]
+
+There are two ways--as a [cmd snit::type], or as an instance of
+a [cmd snit::type].
+
+[subsection {How can I create an ensemble command using an instance of a snit::type?}]
+
+Define a type whose [sectref {INSTANCE METHODS}] are the subcommands
+of your ensemble command.  Then, create an instance of the type with
+the desired name.
+
+[para]
+
+For example, the following code uses [sectref {DELEGATION}] to create
+a work-alike for the standard [cmd string] command:
+
+[example {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--
+[cmd mystring], in this case.
+
+[para]
+
+This method has two drawbacks.  First, it leaves the type command
+floating about.  More seriously, your shiny new ensemble
+command will have [method info] and [method destroy] subcommands that
+you probably have no use for.  But read on.
+
+[subsection {How can I create an ensemble command using a snit::type?}]
+
+Define a type whose [sectref {TYPE METHODS}] are the subcommands
+of your ensemble command.[para]
+
+For example, the following code uses [sectref {DELEGATION}] to create
+a work-alike for the standard [cmd string] command:
+
+[example {snit::type mystring {
+    delegate typemethod * to stringhandler
+
+    typeconstructor {
+        set stringhandler string
+    }
+}
+}]
+
+Now the type command itself is your ensemble command.
+
+[para]
+
+This method has only one drawback, and though it's major, it's 
+also surmountable.  Your new ensemble command will have
+[method create], [method info] and [method destroy] subcommands
+you don't want.  And worse yet, since the [method create] method
+can be implicit, users of your command will accidentally be creating
+instances of your [cmd 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.
+
+[para]
+
+The work around is to set some [sectref {PRAGMAS}], as shown here:
+
+[example {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 [cmd pragma] statement to tell Snit that we don't
+want the [method info] typemethod or the [method destroy] typemethod,
+and that our type has no instances; this eliminates the 
+[method create] typemethod and all related code.  As
+a result, our ensemble command will be well-behaved, with no
+unexpected subcommands.
+
+[section {PRAGMAS}]
+
+[subsection {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.
+
+[subsection {How do I set a pragma?}]
+
+Use the [cmd pragma] statement.  Each pragma is an option with a
+value; each time you use the [cmd pragma] statement you can set one or
+more of them.
+
+[subsection {How can I get rid of the "info" type method?}]
+
+Set the [const -hastypeinfo] pragma to [const no]:
+
+[example {snit::type dog {
+    pragma -hastypeinfo no
+    # ...
+}
+}]
+
+Snit will refrain from defining the [method info] type method.
+
+[subsection {How can I get rid of the "destroy" type method?}]
+
+Set the [const -hastypedestroy] pragma to [const no]:
+
+[example {snit::type dog {
+    pragma -hastypedestroy no
+    # ...
+}
+}]
+
+Snit will refrain from defining the [method destroy] type method.
+
+[subsection {How can I get rid of the "create" type method?}]
+
+Set the [const -hasinstances] pragma to [const no]:
+
+[example {snit::type dog {
+    pragma -hasinstances no
+    # ...
+}
+}]
+
+Snit will refrain from defining the [method 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.
+
+[para]
+
+This is useful if you wish to use a [cmd snit::type] to define
+an ensemble command rather than a type with instances.
+
+[para]
+
+Pragmas [const -hastypemethods] and [const -hasinstances] cannot
+both be false (or there'd be nothing left).
+
+[subsection {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 
+[method create] type method directly.  To get the same behavior from 
+Snit, set the [const -hastypemethods] pragma to [const no]:
+
+[example {snit::type dog {
+    pragma -hastypemethods no
+    #...
+}
+
+# Creates ::spot
+dog spot
+
+# Tries to create an instance called ::create
+dog create spot
+}]
+
+Pragmas [const -hastypemethods] and [const -hasinstances] cannot
+both be false (or there'd be nothing left).
+
+[subsection {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 
+[cmd snit::type], even if the name was already in use by some other
+object or command.  You could do the following, for example:
+
+[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 [const -canreplace] pragma to [const yes]:
+
+[example {snit::type dog {
+    pragma -canreplace yes
+    # ...
+}
+}]
+
+[subsection {How can I make my simple type run faster?}]
+
+In Snit 1.x, you can set the [const -simpledispatch] pragma to [const yes].
+
+[para]
+
+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 
+[const -simpledispatch] pragma allows you to substitute a simpler
+dispatch mechanism that runs quite a bit faster.  The limitations
+are these:
+
+[list_begin itemized]
+
+[item] Methods cannot be delegated.
+[item] [cmd uplevel] and [cmd upvar] do not work as expected: the
+caller's scope is two levels up rather than one.
+[item] The option-handling methods 
+([cmd cget], [cmd configure], and [cmd configurelist]) are very
+slightly slower.
+[list_end]
+
+In Snit 2.2, the [const -simpledispatch] macro is obsolete, and
+ignored; all Snit 2.2 method dispatch is faster than Snit 1.x's 
+[const -simpledispatch].
+
+[section {MACROS}]
+
+[subsection {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.
+
+[subsection {What are macros good for?}]
+
+You can use Snit macros to define new type definition syntax, and to
+support conditional compilation.
+
+[subsection {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?
+
+[para]
+
+It's easily done.  Outside of any type definition, define a macro that
+returns 1 if the extension is available, and 0 otherwise:
+
+[example {if {$gotFastExtension} {
+    snit::macro fastcode {} {return 1}
+} else {
+    snit::macro fastcode {} {return 0}
+}
+}]
+
+Then, use your macro in your type definition:
+
+[example {snit::type dog {
+
+    if {[fastcode]} {
+        # Fast methods
+        method bark {} {...}
+        method wagtail {} {...}
+    } else {
+        # Slow methods
+        method bark {} {...}
+        method wagtail {} {...}
+    }
+}
+}]
+
+[subsection {How do I define new type definition syntax?}]
+
+Use a macro.  For example, your [cmd snit::widget]'s 
+[const -background] option should be propagated to a number
+of component widgets.  You could implement that like this:
+
+[example {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:
+
+[example {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:
+
+[example {snit::widget mywidget {
+    option -background default -white
+    option -foreground default -black
+
+    propagate -background to {comp1 comp2 comp3}
+    propagate -foreground to {comp1 comp2 comp3}
+}
+}]
+
+[subsection {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.
+
+[para]
+
+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.
+
+[para]
+
+If my fancy [cmd snit::widget] is called [cmd ::mylib::mywidget], 
+for example, then I should define my [cmd propagate] macro as
+[cmd ::mylib::propagate]:
+
+
+[example {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}
+}
+}]
+
+
+[section {BUGS, IDEAS, FEEDBACK}]
+
+This document, and the package it describes, will undoubtedly contain
+bugs and other problems.
+
+Please report such in the category [emph snit] of the
+[uri {http://sourceforge.net/tracker/?group_id=12883} {Tcllib SF Trackers}].
+
+Please also report any ideas for enhancements you may have for either
+package and/or documentation.
+
+
+[keywords class {object oriented} object C++]
+[keywords {Incr Tcl} BWidget]
+[keywords widget adaptors {widget adaptors} {mega widget}]
+[manpage_end]