package require snit 0.93 ::snit::type name definition ::snit::widget name definition ::snit::widgetadaptor name definition
This man page is intended to be a reference only; see the accompanying Snit FAQ list for a gentler, more tutorial introduction to Snit concepts.
snit::type name definition
snit::type
command appears (usually the global namespace). It
returns the fully qualified type name.The type name is then a command which is used to create objects of the new type, along with other activities.
The snit::type
definition block may contain the
following definitions:
typevariable name ?value?
typemethod name arglist body
The arglist is a normal Tcl argument list and may contain default arguments and the "args" argument; however, it may not contain the argument names "type", "self", "selfns", or "win".
Type variables defined in the type definition are automatically visible in the body of every type method.
typeconstructor body
The variable "type" is automatically defined in the body to the type's fully-qualified name.
Type variables defined in the type definition are automatically visible in the body of every type method.
A type may define at most one type constructor.
option namespec ?defaultValue?
The namespec is a list defining the option's name, resource name, and class name, e.g.:
option {-font font Font} {Courier 12}
The option name must begin with a hyphen, and must not contain any upper case letters. The resource name and class name are optional; if not specified, the resource name defaults to the option name, minus the hyphen, and the class name defaults to the resource name with the first letter capitalized. Thus, the following statement is equivalent to the previous example:
option -font {Courier 12}
See the Snit FAQ list for more information about resource and class names.
Options are normally set and retrieved using the
standard configure
and cget
instance
methods.
variable name ?value?
Note that the delegate
statement implicitly
defines an instance variable for the named component.
method name arglist body
args
The arglist is a normal Tcl argument list and may
contain default arguments and the "args" argument. In
addition, the method is implicitly passed the following
arguments as well: "type", which contains the
fully-qualified type name; "self", which contains the
current instance command name; "selfns", which contains
the name of the instance's private namespace; and
"win", which contains the original instance name.
Consequently, the arglist may not contain the
argument names "type", "self", "selfns", or "win".An instance method defined in this way is said to be "locally defined".
Type and instance variables defined in the type definition are automatically visible in all instance methods. If the type has locally defined options, the "options" array is also visible.
constructor arglist body
The arglist is a normal Tcl argument list and may contain default arguments and the "args" argument. As with methods, the arguments "type", "self", "selfns", and "win", are defined implicitly.
If the constructor is not defined, it defaults to this:
constructor {args} { $self configurelist $args }
For standard Tk widget behavior (or to achieve the behavior of previous versions of snit) the argument list should be the single name "args", as shown.
destructor body
As with arguments, the parameters "type", "self", "selfns", and "win", are defined implicitly.
onconfigure name arglist body
The arglist may contain exactly one argument name. As with methods, the arguments "type", "self", "selfns", and "win", are defined implicitly.
If no explicit onconfigure handler is defined for an option, the handler is defined as follows:
onconfigure name {value} { set options(name) $value }If an explicit onconfigure handler is defined, the options array will be updated with the new value only if the handler so updates it.
oncget name body
The variables "type", "self", "selfns", and "win" are
defined as usual in the handler's body. Whatever
the handler returns will be the return value of the call
to the cget
instance method.
If no explicit oncget handler is defined for an option, the handler is defined as follows:
oncget name { return $options(name) }
proc name args body
Although they are not implicitly defined for procs, the argument names "type", "self", "selfns", and "win" should be avoided.
delegate method name to comp
delegate method name to comp as target
delegate method * to comp
delegate method * to comp except exceptions
method name {args...} { $comp mymethod args... }If desired, the delegated method may target a method with a different name by using the "as" clause; the target may also include arguments to add to the beginning of the argument list.
The form "delegate method *" delegates all unknown method names to the specified comp. The "except" clause can be used to specify a list of exceptions, i.e., method names that will not be so delegated.
A method cannot be both locally defined and delegated.
delegate option namespec to comp
delegate option namespec to comp as target
delegate option * to comp
delegate option * to comp except exceptions
option
statement. When the
configure
,
configurelist
, or
cget
instance method is used to set or
retrieve the option's value, the equivalent configure or
cget command will be applied to the component as though
these onconfigure
and
oncget
handlers were
defined, where name is the option name from the
namespec:
onconfigure name {value} { $comp configure name $value } oncget name { return [$comp cget name] }If the "as" clause is specified, then the target option name is used in place of name.
The form "delegate option *" delegates all unknown method names to the specified comp. The "except" clause can be used to specify a list of exceptions, i.e., option names that will not be so delegated.
Warning: options can only be delegated to a component if it supports the "configure" and "cget" instance methods.
Note that an option cannot be both locally defined and delegated.
expose comp
expose comp as method
This differs from delegation in that it maps an instance method to the component itself instead of to one of the component's methods.
Calling the new instance method is just like calling the component, except that if the method is called with no arguments it returns the component.
snit::widget name definition
snit::type
. A snit::widget
differs from a snit::type
in these ways:
hull
, which is normally
a Tk frame widget. Other widgets created as part of the megawidget
will be created within this frame.
The hull component is initially created with the
requested widget name; then Snit does some magic,
renaming the hull component and installing its own
instance command in its place. The hull component's new
name is saved in an instance variable called
hull
.
snit::widget
definition can include any of
statements allowed in a snit::type
definition,
and may also include these as well:
widgetclass name
snit::widget
's widget class
to name, overriding the default. See
the Snit FAQ list for more
information about the Tk option database.
hulltype type
snit::widget
's hull. The type may
be frame
(the default) or
toplevel
.
snit::widgetadaptor name definition
snit::widget
in that the
instance's hull
component is not created
automatically, but is created in the constructor and installed
using the installhull
command. Once the hull is
installed, its instance command is renamed and replaced as with
normal snit::widgets
. The original command is
again accessible in the instance variable hull
.
Note that in general it is not possible to change the
widget class of a
snit::widgetadaptor
's hull widget. See
the Snit FAQ list for more information
on how snit::widgetadaptors
interact with the Tk option database.
snit::typemethod type
name arglist body
snit::method type
name arglist body
$type typemethod args....
$type create name ?option value ...?
For snit::types
, if name is not a fully-qualified
command name, it is assumed to be a name in the namespace in
which the call to snit::type
appears. The method returns the
fully-qualified instance name.
For snit::widgets
and
snit::widgetadaptors
, name must be a valid
widget name; the method returns the widget name.
So long as name does not conflict with any defined type method name, the "create" keyword may be omitted.
If the name includes the string "%AUTO%", it will be replaced with the string "$type$counter" where "$type" is the type name and "$counter" is a counter that increments each time "%AUTO%" is used for this type.
By default, any arguments following the name will be a list of option names and their values; however, a type's constructor can specify a different argument list.
$type info typevars ?pattern?
If pattern is given, it's used as a string
match
pattern; only names which match the pattern are
returned.
$type info instances ?pattern?
snit::type
s, it
will be a list of fully-qualified instance names; for
snit::widgets, it will be a list of Tk widget names.
If pattern is given, it's used as a string
match
pattern; only names which match the pattern are
returned.
$type destroy
snit::types
; snit::widgets
use the Tk
destroy
command instead.
create
type method creates
objects of the type; each object has a unique name which is also a
Tcl command. This command is used to access the object's methods and
data, and has this form:
$object method args...
$object configure ?option? ?value? ...
Warning: this information will be available for delegated options only if the component to which they are delegated has a "configure" method that returns this same kind of information.
$object configurelist optionlist
configure
, but takes
one argument, a list of options and
their values. It's mostly useful in the type constructor, but
can be used anywhere.
$object cget option
$object destroy
destructor
and
freeing all related memory.
Note: The "destroy" method isn't defined for
snit::widget
or
snit::widgetadaptor
objects; instances of these are destroyed by calling the Tk
"destroy" command, just as a normal widget is.
$object info type
$object info vars ?pattern?
If pattern is given, it's used as a string
match
pattern; only names which match the pattern are
returned.
$object info typevars ?pattern?
If pattern is given, it's used as a string
match
pattern; only names which match the pattern are
returned.
$object info options ?pattern?
If pattern is given, it's used as a string
match
pattern; only names which match the pattern are
returned.
Note that the return value might be different for different instances of the same type, if component object types can vary from one instance to another.
varname name
typevarname name
codename name
from argvName option ?defvalue?
from
command plucks an
option value from a list of options and their values, such as
is passed into a type's
constructor
.
argvName must be the name of a variable containing such
a list; option is the name of the specific option.
from
looks for option in the option list. If
it is found, it and its value are removed from the list, and
the value is returned. If option doesn't appear in the
list, then the defvalue is returned. If the option is a
normal (undelegated) option, and defvalue is not
specified, then the option's default value as specified in the
type definition will be returned instead.
variable name
variable
command, if
desired; or, instance code can use the
variable
command to declare instance variables that don't appear in the
type definition.It's generally best to define all instance variables in the type definition, and omit declaring them in methods and so forth.
Note that this is not the same as the standard Tcl "::variable" command.
typevariable name
typevariable
to
declare type variables explicitly, if
desired; or, they can use typevariable
to declare type variables that don't appear in the type definition.It's generally best to declare all type variables in the type definition, and omit declaring them in methods, type methods, and so forth.
install compName using
objType objName args...
If this is a snit::type
, then the following two
commands are equivalent:
install myComp using myObjType $self.myComp options... set myComp [myObjType $self.myComp options...]Note that whichever method is used, compName must still be declared in the type definition using variable, or must be referenced in at least one
delegate
statement.
If this is a snit::widget
or
snit::widgetadaptor
, and if options have been
delegated to component compName, then those options
will receive default values from the Tk option database. Note
that it doesn't matter whether the component to be installed is
a widget or not. See the Snit FAQ list
for more information about the Tk
Option Database.
installhull using widgetType args...
installhull name
snit::widgetadaptor
must
create a widget to be the object's hull component; the widget is
installed as the hull component using this command.
This command has two forms. The first form specifies the
widgetType and the args... (that is, the
hardcoded option list) to use in creating the hull. Given
this form, installhull
creates the hull widget,
and initializes any options delegated to the hull from the Tk
option database.
In the second form, the hull widget has already been created;
note that its name must be "$win". In this case, the Tk
option database is not queried for any options
delegated to the hull. See the Snit FAQ
list for more information about
snit::widgetadaptors
and the Tk option database.
The longer form is preferred; however, the shorter form allows the programmer to adapt a widget created elsewhere, which is sometimes useful. For example, it can be used to adapt a "page" widget created by a BWidgets tabbed notebook or pages manager widget.
mymethod name ?args...?
mymethod
command is used for formatting
callback commands to be passed to other objects. It returns a
command that when called will invoke method name with
the specified arguments, plus of course any arguments added by
the caller. In other words, both of the following commands
will cause my object's dosomething
method to be
called when $button
is pressed:
$button configure -command [list $self dosomething myargument] $button configure -command [mymethod dosomething myargument]The chief distinction between the two is that the latter form will not break if the creator of my object renames its object command.
dog
object
has a tail
object:
snit::type dog { variable mytail constructor {args} { set mytail [tail %AUTO% -partof $self] $self configurelist $args } method wag {} { $mytail wag } } snit::type tail { option -length 5 option -partof method wag {} { return "Wag, wag, wag."} }Because the
tail
object's name is stored in an instance
variable, it's easily accessible in any method.
As of Snit 0.84, the install
command provides an alternate way to create and install the
component:
snit::type dog { variable mytail constructor {args} { install mytail using tail %AUTO% -partof $self $self configurelist $args } method wag {} { $mytail wag } }For
snit::types
, the two methods are equivalent; for
snit::widgets
and snit::widgetadaptors
,
the "install" command properly initializes delegated options by
querying the Tk option database. See the Snit FAQ
list for more information.
In the above examples, the dog
object's "wag" method
simply calls the tail
component's "wag" method. In OO
circles, this is called delegation. Snit provides an easier way to do
this, as shown:
snit::type dog { delegate method wag to mytail constructor {args} { set mytail [tail %AUTO% -partof $self] $self configurelist $args } }The
delegate
statement in the type definition implicitly
defines the instance variable mytail
to hold the
component's name; it also defines the dog
object's "wag"
method, delegating it to the tail
component.If desired, all otherwise unknown methods can be delegated to a specific component:
snit::type dog { delegate method * to mytail constructor {args} { set mytail [tail %AUTO% -partof $self] $self configurelist $args } method bark { return "Bark, bark, bark!" } }In this case, a
dog
object will handle its own
"bark" method; but "wag" will be passed along to mytail
.
Any other method, being recognized by neither dog
nor
tail
, will simply raise an error.Option delegation is similar to method delegation, except for the interactions with the Tk option database; this is described in the Snit FAQ list.
So that was one thing--tedium is a powerful motivator. But the other thing I noticed is that I wasn't using inheritance at all, and I wasn't missing it. Instead, I was using delegation: objects that created other objects and delegated methods to them.
And I said to myself, "This is getting tedious...there has got to be a better way." And one afternoon, on a whim, I started working on Snit, an object system that works the way Tcl works. Snit doesn't support inheritance, but it's great at delegation, and it makes creating megawidgets easy.
I should add, I'm not particularly down on Incr Tcl. But "Snit's Not Incr Tcl" occurred to me while I was casting about for a name, and I guess there was a certainly inevitability about it.
If you have any comments or suggestions (or bug reports!) don't hesitate to send me e-mail at will@wjduquette.com. In addition, there's now a Snit mailing list; you can find out more about it at the Snit home page, http://www.wjduquette.com/snit. Finally, Snit is now part of tcllib, the standard Tcl library; you can also add bug reports to the tcllib bug database at SourceForge.
Copyright © 2004, by William H. Duquette. All rights reserved.