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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

namespace import [namespace parent]::*

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

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

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

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

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

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

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

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

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

You create an instance of a snit::type by passing the new
instance's name to the type's create method. In the following
example, we create a dog object called spot.

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

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

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

This document generally uses the shorter form.

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

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

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

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

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

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

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

.btn configure -command [list $self ButtonPress]

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

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

.btn configure -command [mymethod ButtonPress]

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

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

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

Any Snit object of any type can be destroyed by renaming
it to the empty string using the Tcl rename command.

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

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.

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

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

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

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

It's often useful to define private methods, that is, instance methods
intended to be called only by other methods of the same object.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

In Tk, it's common to pass a widget a variable name; for example, Tk
label widgets have a -textvariable option which names the
variable which will contain the widget's text. This allows the
program to update the label's value just by assigning a new value to
the variable.

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

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

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

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

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

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

Any number of options may be set at one time using the
configure instance method. Suppose that closer inspection
shows that ::fido is not a brown mongrel, but rather a rare Arctic Boar
Hound of a lovely dun color:

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

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

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

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

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

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

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

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

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

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

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

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.

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

In Tk, it's common to pass a widget a variable name; for example, Tk
label widgets have a -textvariable option which names the
variable which will contain the widget's text. This allows the
program to update the label's value just by assigning a new value to
the variable.

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

There are two ways to do this. The preferred way is to write a pair
of TYPE METHODS to set and query the type variable's value.

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

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

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

Method argument lists are defined just like normal Tcl proc argument
lists; in particular, they can include arguments with default values
and the args argument.

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

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

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

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

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

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

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

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

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

If you don't provide a constructor explicitly, you get the default
constructor, which is identical to the explicitly-defined
constructor shown here:

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

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

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

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

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

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

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

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

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

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

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

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

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

An owned component is a component whose object command's
lifetime is controlled by the snit::type or snit::widget.

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

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.

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

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

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

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

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

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

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

install mytail using tail %AUTO%

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

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

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

Yes, and there are two ways to do it. The most appropriate way is
usually to use DELEGATION. Delegation allows you to pass
the options and methods you specify along to particular components.
This effectively hides the components from the users of your type, and
ensures good encapsulation.

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

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

Declare a type component using the typecomponent statement. It
takes the same options (-inherit and -public) as the
component statement does, and defines a type variable to hold
the type component's object command.

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

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

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

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

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

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

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

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

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

Suppose the tail's wag method takes as an argument the
number of times the tail should be wagged. You want to delegate the
dog's wagtail method to the tail's wag
method, specifying that the tail should be wagged exactly three times.
This is easily done, too:

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

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

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

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

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

Use the delegate typemethod statement. It works like
delegate method, with these differences: first, it defines
a type method instead of an instance method; second, the
using clause ignores the %s, %n,
and %w %-conversions.

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

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

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

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

In the previous answer we delegated the dog's -length
option down to its tail. This is, of course, wrong. The dog
has a length, and the tail has a length, and they are different. What
we'd really like to do is give the dog a -taillength
option, but delegate it to the tail's -length option:

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

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

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

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

In the previous answer, we said that every dog is
an animal by delegating all unknown methods and options to the
animal component. But what if the animal type has some
methods or options that we'd like to suppress?

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

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

The name of an instance of a snit::type can be any valid Tcl
command name, in any namespace.
The name of an instance of a snit::widget must be a valid Tk
widget name, and its parent widget must already exist.

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

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

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

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

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

A snit::widget's hull component will usually be a Tk frame
widget; however, it may be any Tk widget that defines the
-class option. You can
explicitly choose the hull type you prefer by including the hulltype
command in the widget definition:

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

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

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

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

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

Use the snit::widgetadaptor command. The definition for a
snit::widgetadaptor looks just like that for a snit::type
or snit::widget, except that the constructor must create and
install the hull component.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Every Tk widget has a "widget class": a name that is used when adding
option settings to the database. For Tk widgets, the widget class is
the same as the widget command name with an initial capital. For
example, the widget class of the Tk button widget is
Button.

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

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

is ScrolledText.

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

snit::widget ::mylibrary::scrolledText {
widgetclass Text
# ...
}

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

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

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

For options implicitly delegated to a component using
delegate option *, the resource and class names will be
exactly those defined by the component. The configure method
returns these names, along with the option's default and current
values:

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:

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,

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

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

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

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

The value of C is also "red", because -background is implicitly
delegated to the hull; thus, retrieving it is the same as retrieving
-hullbackground. Note that this case is unusual; the
-background option should probably have been excluded using the delegate
statement's except clause, or (more likely) delegated to some other
component.

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

delegate option {-borderwidth borderWidth BorderWidth} to hull

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

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

set hull [text $win -foreground white]

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

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

installhull [text $win -foreground white]

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

For hull components, Snit assumes that Tk will do most of the work
automatically. Non-hull components are somewhat more complicated, because
they are matched against the option database twice.

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

But then, the option database is queried for all options delegated to
the component, and the component is initialized accordingly--provided
that the install command is used to create it.

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

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

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

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

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

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

A snit::type never queries the option database.
However, a snit::widget can have non-widget components. And if
options are delegated to those components, and if the install
command is used to install those components, then they will be
initialized from the option database just as widget components are.

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

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

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

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

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

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

Normal Tk widget type commands don't have subcommands; all they do is
create widgets--in Snit terms, the type command calls the
create type method directly. To get the same behavior from
Snit, set the -hastypemethods pragma to no:

Up until Snit 0.95, you could use any name for an instance of a
snit::type, even if the name was already in use by some other
object or command. You could do the following, for example:

snit::type dog { ... }
dog proc

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

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

Methods cannot be delegated.

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

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

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

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

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

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

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

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

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