1 [comment {-*- tcl -*- doctools manpage}]
2 [manpage_begin snit n 2.3.2]
3 [copyright {2003-2009, by William H. Duquette}]
4 [moddesc {Snit's Not Incr Tcl, OO system}]
5 [titledesc {Snit's Not Incr Tcl}]
6 [category {Programming tools}]
8 [require snit [opt 2.3.2]]
12 Snit is a pure Tcl object and megawidget system. It's
13 unique among Tcl object systems in that it's based not on inheritance
14 but on delegation. Object systems based on inheritance only allow you
15 to inherit from classes defined using the same system, which is
16 limiting. In Tcl, an object is
17 anything that acts like an object; it shouldn't matter how the object
18 was implemented. Snit is intended to help you build applications out of
19 the materials at hand; thus, Snit is designed to be able to
20 incorporate and build on any object, whether it's a hand-coded object,
21 a [package Tk] widget, an [package {Incr Tcl}] object,
22 a [package BWidget] or almost anything else.
26 This man page is intended to be a reference only; see the accompanying
27 [cmd snitfaq] for a gentler, more tutorial introduction to Snit
30 [section {SNIT VERSIONS}]
32 This man page covers both Snit 2.2 and Snit 1.3. The primary
33 difference between the two versions is simply that Snit 2.2 contains
34 speed optimizations based on new features of Tcl 8.5; Snit 1.3
35 supports all of Tcl 8.3, 8.4 and Tcl 8.5. There are a few minor
36 inconsistencies; they are flagged in the body of the man page with the
37 label "Snit 1.x Incompatibility"; they are also discussed in the [cmd snitfaq].
43 [subsection {Type and Widget Definitions}]
45 Snit provides the following commands for defining new types:
47 [list_begin definitions]
49 [call [cmd snit::type] [arg name] [arg definition]]
51 Defines a new abstract data type called [arg name]. If [arg name] is
52 not a fully qualified command name, it is assumed to be a name in the
53 namespace in which the [cmd snit::type] command was called (usually the
54 global namespace). It returns the fully qualified name of the new type.
58 The type name is then a command that is used to create objects of the
59 new type, along with other activities.
63 The [cmd snit::type] [arg definition] block is a script that may
64 contain the following definitions:
66 [list_begin definitions]
67 [call [cmd typevariable] [arg name] [opt [const -array]] [opt [arg value]]]
69 Defines a type variable with the specified [arg name], and optionally
70 the specified [arg value]. Type variables are shared by all instances
71 of the type. If the [const -array] option is included, then
72 [arg value] should be a dictionary; it will be
73 assigned to the variable using [cmd "array set"].
75 [call [cmd typemethod] [arg name] [arg arglist] [arg body]]
77 Defines a type method, a subcommand of the new type command,
78 with the specified name, argument list, and
79 body. The [arg arglist] is a normal Tcl argument list and may contain
80 default arguments and the [var args] argument; however, it may not
81 contain the argument names [var type], [var self], [var selfns], or
86 The variable [var type] is automatically defined in the [arg body] to
87 the type's fully-qualified name. In addition,
88 type variables are automatically visible in the [arg body]
93 If the [arg name] consists of two or more tokens, Snit handles it specially:
95 [example { typemethod {a b} {arg} { puts "Got $arg" }
98 This statement implicitly defines a type method called [const a] which
99 has a subcommand [const b]. [const b] is called like this:
101 [example { $type a b "Hello, world!"
104 [const a] may have any number of subcommands. This makes it possible
105 to define a hierarchical command structure; see [cmd method], below,
110 Type methods can call commands from the namespace in which the type is
111 defined without importing them, e.g., if the type name is
112 [cmd ::parentns::typename], then the type's type methods can call
113 [cmd ::parentns::someproc] just as [cmd someproc].
114 [emph {Snit 1.x Incompatibility:}] This does not work in Snit 1.x, as
115 it depends on [cmd "namespace path"], a new command in Tcl 8.5.
119 [emph {Snit 1.x Incompatibility:}] In Snit 1.x, the following
120 following two calls to this type method are equivalent:
122 [example { $type a b "Hello, world!"
123 $type {a b} "Hello, world!"
126 In Snit 2.2, the second form is invalid.
128 [call [cmd typeconstructor] [arg body]]
130 The type constructor's [arg body] is executed once when the
131 type is first defined; it is typically used to
132 initialize array-valued type variables and to add
133 entries to [sectref {The Tk Option Database}].
137 The variable [var type] is automatically defined in the [arg body],
138 and contains the type's fully-qualified name. In addition,
139 type variables are automatically visible in the [arg body] of the type
144 A type may define at most one type constructor.
148 The type constructor can call commands from the namespace in which the type is
149 defined without importing them, e.g., if the type name is
150 [cmd ::parentns::typename], then the type constructor can call
151 [cmd ::parentns::someproc] just as [cmd someproc].
152 [emph {Snit 1.x Incompatibility:}] This does not work in Snit 1.x, as
153 it depends on [cmd "namespace path"], a new command in Tcl 8.5.
155 [call [cmd variable] [arg name] [opt [const -array]] [opt [arg value]]]
157 Defines an instance variable, a private variable associated with each
158 instance of this type, and optionally its initial value.
159 If the [const -array] option is included, then
160 [arg value] should be a dictionary; it will be
161 assigned to the variable using [cmd "array set"].
163 [call [cmd method] [arg name] [arg arglist] [arg body]]
165 Defines an instance method, a subcommand of each instance of this
166 type, with the specified name, argument list and body.
167 The [arg arglist] is a normal Tcl argument list and may contain
168 default arguments and the [var args] argument.
172 The method is implicitly passed the following arguments as well:
174 [var type], which contains the fully-qualified type name; [var self],
175 which contains the current instance command name; [var selfns], which
176 contains the name of the instance's private namespace; and [var win],
177 which contains the original instance name.
179 Consequently, the [arg arglist] may not contain the argument names
180 [const type], [const self], [const selfns], or [const win].
184 An instance method defined in this way is said to be
185 [term {locally defined}].
189 Type and instance variables are
190 automatically visible in all instance methods. If the type has
191 locally defined options, the [var options] array is also visible.
195 If the [arg name] consists of two or more tokens, Snit handles it specially:
197 [example { method {a b} {} { ... }
200 This statement implicitly defines a method called [const a] which
201 has a subcommand [const b]. [const b] is called like this:
203 [example { $self a b "Hello, world!"
206 [const a] may have any number of subcommands. This makes it possible
207 to define a hierarchical command structure:
209 [example {% snit::type dog {
210 method {tail wag} {} {return "Wag, wag"}
211 method {tail droop} {} {return "Droop, droop"}
223 What we've done is implicitly defined a "tail" method with subcommands
224 "wag" and "droop". Consequently, it's an error to define "tail"
229 Methods can call commands from the namespace in which the type is
230 defined without importing them, e.g., if the type name is
231 [cmd ::parentns::typename], then the type's methods can call
232 [cmd ::parentns::someproc] just as [cmd someproc].
233 [emph {Snit 1.x Incompatibility:}] This does not work in Snit 1.x, as
234 it depends on [cmd "namespace path"], a new command in Tcl 8.5.
238 [emph {Snit 1.x Incompatibility:}] In Snit 1.x, the following
239 following two calls to this method are equivalent:
241 [example { $self a b "Hello, world!"
242 $self {a b} "Hello, world!"
245 In Snit 2.2, the second form is invalid.
247 [call [cmd option] [arg namespec] [opt [arg defaultValue]]]
248 [call [cmd option] [arg namespec] [opt [arg options...]]]
250 Defines an option for instances of this type, and optionally gives it
251 an initial value. The initial value defaults to the empty string if
252 no [arg defaultValue] is specified.
256 An option defined in this way is said to be [term {locally defined}].
260 The [arg namespec] is a list defining the option's
261 name, resource name, and class name, e.g.:
263 [example { option {-font font Font} {Courier 12}
266 The option name must begin with a hyphen, and must not contain any
267 upper case letters. The resource name and class name are optional; if
268 not specified, the resource name defaults to the option name, minus
269 the hyphen, and the class name defaults to the resource name with the
270 first letter capitalized. Thus, the following statement is equivalent
271 to the previous example:
273 [example { option -font {Courier 12}
276 See [sectref {The Tk Option Database}] for more information about
277 resource and class names.
281 Options are normally set and retrieved using the standard
282 instance methods [method configure] and [method cget]; within instance code
283 (method bodies, etc.), option values are available through the
286 [example { set myfont $options(-font)
289 If the type defines any option handlers (e.g., [const -configuremethod]),
290 then it should probably use [method configure] and [method cget] to
291 access its options to avoid subtle errors.
295 The [cmd option] statement may include the following options:
297 [list_begin definitions]
298 [def "[const -default] [arg defvalue]"]
300 Defines the option's default value; the option's default value
301 will be "" otherwise.
303 [def "[const -readonly] [arg flag]"]
305 The [arg flag] can be any Boolean value recognized by Tcl.
306 If [arg flag] is true, then the option is read-only--it can only
307 be set using [method configure] or [method configurelist]
308 at creation time, i.e., in the type's constructor.
310 [def "[const -type] [arg type]"]
312 Every locally-defined option may define its validation type, which may
313 be either the name of a validation type or a specification for a
318 For example, an option may declare that its value must be an integer
319 by specifying [cmd snit::integer] as its validation type:
321 [example { option -number -type snit::integer
324 It may also declare that its value is an integer between 1 and 10
325 by specifying a validation subtype:
327 [example { option -number -type {snit::integer -min 1 -max 10}
330 If a validation type or subtype is defined for an option, then
331 it will be used to validate the option's value whenever it is
332 changed by the object's [method configure] or
333 [method configurelist] methods. In addition, all such options
334 will have their values validated automatically immediately
335 after the constructor executes.
339 Snit defines a family of validation types and subtypes, and it's
340 quite simple to define new ones. See
341 [sectref "Validation Types"] for the complete list, and
342 [sectref "Defining Validation Types"] for an explanation of how
345 [def "[const -cgetmethod] [arg methodName]"]
347 Every locally-defined option may define a [const -cgetmethod];
348 it is called when the option's value is retrieved using the
349 [method cget] method. Whatever the method's [arg body] returns will
350 be the return value of the call to [method cget].
354 The named method must take one argument, the option name.
355 For example, this code is equivalent to (though slower than)
356 Snit's default handling of [cmd cget]:
358 [example { option -font -cgetmethod GetOption
359 method GetOption {option} {
360 return $options($option)
364 Note that it's possible for any number of options to share a
367 [def "[const -configuremethod] [arg methodName]"]
369 Every locally-defined option may define a [const -configuremethod];
370 it is called when the option's value is set using the
371 [method configure] or [method configurelist] methods. It is the
372 named method's responsibility to save the option's value; in other
373 words, the value will not be saved to the [var options()] array unless
374 the method saves it there.
378 The named method must take two arguments, the option name and
379 its new value. For example, this code is equivalent to
380 (though slower than) Snit's default handling of [cmd configure]:
382 [example { option -font -configuremethod SetOption
383 method SetOption {option value} {
384 set options($option) $value
388 Note that it's possible for any number of options to share a
389 single [const -configuremethod].
391 [def "[const -validatemethod] [arg methodName]"]
393 Every locally-defined option may define a [const -validatemethod];
394 it is called when the option's value is set using the
395 [method configure] or [method configurelist] methods, just before
396 the [const -configuremethod] (if any). It is the
397 named method's responsibility to validate the option's new value,
398 and to throw an error if the value is invalid.
402 The named method must take two arguments, the option name and
403 its new value. For example, this code verifies that
404 [const -flag]'s value is a valid Boolean value:
406 [example { option -font -validatemethod CheckBoolean
407 method CheckBoolean {option value} {
408 if {![string is boolean -strict $value]} {
409 error "option $option must have a boolean value."
414 Note that it's possible for any number of options to share a
415 single [const -validatemethod].
419 [call [cmd constructor] [arg arglist] [arg body]]
421 The constructor definition specifies a [arg body] of code to be
422 executed when a new instance is created. The [arg arglist] is a
423 normal Tcl argument list and may contain default arguments and
424 the [var args] argument.
428 As with methods, the arguments [var type], [var self], [var selfns],
429 and [var win] are defined implicitly, and all type and instance
430 variables are automatically visible in its [arg body].
434 If the [arg definition] doesn't explicitly define the constructor,
435 Snit defines one implicitly. If the type declares at least one option
436 (whether locally or by delegation), the default constructor will
437 be defined as follows:
439 [example { constructor {args} {
440 $self configurelist $args
444 For standard Tk widget behavior, the argument list should be
445 the single name [const args], as shown.
449 If the [arg definition] defines neither a constructor nor
450 any options, the default constructor is defined as follows:
452 [example { constructor {} {}
455 As with methods, the constructor can call commands from the namespace
457 defined without importing them, e.g., if the type name is
458 [cmd ::parentns::typename], then the constructor can call
459 [cmd ::parentns::someproc] just as [cmd someproc].
460 [emph {Snit 1.x Incompatibility:}] This does not work in Snit 1.x, as
461 it depends on [cmd "namespace path"], a new command in Tcl 8.5.
463 [call [cmd destructor] [arg body]]
465 The destructor is used to code any actions that must take place when
466 an instance of the type is destroyed: typically, the destruction of
467 anything created in the constructor.
471 The destructor takes no explicit arguments; as with methods, the
472 arguments [var type], [var self], [var selfns], and [var win], are
473 defined implicitly, and all type and instance
474 variables are automatically visible in its [arg body].
476 As with methods, the destructor can call commands from the namespace
478 defined without importing them, e.g., if the type name is
479 [cmd ::parentns::typename], then the destructor can call
480 [cmd ::parentns::someproc] just as [cmd someproc].
481 [emph {Snit 1.x Incompatibility:}] This does not work in Snit 1.x, as
482 it depends on [cmd "namespace path"], a new command in Tcl 8.5.
484 [call [cmd proc] [arg name] [arg args] [arg body]]
486 Defines a new Tcl procedure in the type's namespace.
490 The defined proc differs from a normal Tcl proc in that all type
491 variables are automatically visible. The proc can access
492 instance variables as well, provided that it is passed
493 [var selfns] (with precisely that name) as one of its arguments.
497 Although they are not implicitly defined for procs, the argument names
498 [const type], [const self], and [const win] should be avoided.
502 As with methods and typemethods, procs can call commands from the namespace
504 defined without importing them, e.g., if the type name is
505 [cmd ::parentns::typename], then the proc can call
506 [cmd ::parentns::someproc] just as [cmd someproc].
507 [emph {Snit 1.x Incompatibility:}] This does not work in Snit 1.x, as
508 it depends on [cmd "namespace path"], a new command in Tcl 8.5.
510 [call [cmd delegate] [const method] [arg name] [const to] [arg comp] [opt "[const as] [arg target]"]]
512 Delegates method [arg name] to component [arg comp]. That is, when
513 method [arg name] is called on an instance of this type, the method
514 and its arguments will be passed to the named component's command
515 instead. That is, the following statement
517 [example { delegate method wag to tail
520 is roughly equivalent to this explicitly defined method:
522 [example { method wag {args} {
523 uplevel $tail wag $args
527 As with methods, the [arg name] may have multiple tokens; in this
528 case, the last token of the name is assumed to be the name of the
533 The optional [const as] clause allows you to specify the delegated
534 method name and possibly add some arguments:
536 [example { delegate method wagtail to tail as "wag briskly"
541 A method cannot be both locally defined and delegated.
545 [const Note:] All forms of [cmd "delegate method"] can delegate to
546 both instance components and type components.
548 [call [cmd delegate] [const method] [arg name] [opt "[const to] [arg comp]"] [const using] [arg pattern]]
550 In this form of the [cmd delegate] statement, the [const using] clause
551 is used to specify the precise form of the command to which method
552 [arg name] name is delegated. In this form, the [const "to"] clause is
553 optional, since the chosen command might not involve any particular
558 The value of the [const using] clause is a list that may contain
559 any or all of the following substitution codes; these codes are
560 substituted with the described value to build the delegated command
561 prefix. Note that the following two statements are equivalent:
563 [example { delegate method wag to tail
564 delegate method wag to tail using "%c %m"
567 Each element of the list becomes a single element of the delegated
568 command--it is never reparsed as a string.
573 [list_begin definitions]
576 This is replaced with a single "%". Thus, to pass the string "%c"
577 to the command as an argument, you'd write "%%c".
581 This is replaced with the named component's command.
585 This is replaced with the final token of the method [arg name]; if
586 the method [arg name] has one token, this is identical to [const %M].
590 This is replaced by the method [arg name]; if the [arg name] consists
591 of multiple tokens, they are joined by space characters.
595 This is replaced by the method [arg name]; if the [arg name] consists
596 of multiple tokens, they are joined by underscores ("_").
600 This is replaced with the fully qualified type name.
604 This is replaced with the name of the instance's private namespace.
608 This is replaced with the name of the instance command.
612 This is replaced with the original name of the instance command; for
613 Snit widgets and widget adaptors, it will be the Tk window name.
614 It remains constant, even if the instance command is renamed.
618 [call [cmd delegate] [const method] [const *] [opt "[const to] [arg comp]"] [opt "[const using] [arg pattern]"] [opt "[const except] [arg exceptions]"]]
620 The form [cmd "delegate method *"] delegates all unknown method names to the
621 specified [arg comp]onent. The [const except] clause can be used to
622 specify a list of [arg exceptions], i.e., method names that will not
623 be so delegated. The [const using] clause is defined as given above.
624 In this form, the statement must contain the [const to] clause, the
625 [const using] clause, or both.
629 In fact, the "*" can be a list of two or more tokens whose last
630 element is "*", as in the following example:
632 [example { delegate method {tail *} to tail
635 This implicitly defines the method [cmd tail] whose subcommands will
636 be delegated to the [var tail] component.
638 [call [cmd delegate] [const option] [arg namespec] [const to] [arg comp]]
639 [call [cmd delegate] [const option] [arg namespec] [const to] [arg comp] [const as] [arg target]]
641 [call [cmd delegate] [const option] [const *] [const to] [arg comp]]
642 [call [cmd delegate] [const option] [const *] [const to] [arg comp] [const except] [arg exceptions]]
644 Defines a delegated option; the [arg namespec] is defined as for the
645 [cmd option] statement.
647 When the [method configure], [method configurelist], or [method cget]
648 instance method is used to set or retrieve the option's value, the
649 equivalent [method configure] or [method cget] command will be applied
650 to the component as though the option was defined with the following
651 [const -configuremethod] and [const -cgetmethod]:
653 [example { method ConfigureMethod {option value} {
654 $comp configure $option $value
657 method CgetMethod {option} {
658 return [$comp cget $option]
662 Note that delegated options never appear in the [var options] array.
666 If the [const as] clause is specified, then the [arg target] option
667 name is used in place of [arg name].
671 The form [cmd "delegate option *"] delegates all unknown options to the
672 specified [arg comp]onent. The [const except] clause can be used to
673 specify a list of [arg exceptions], i.e., option names that will not
678 Warning: options can only be delegated to a component if it supports
679 the [method configure] and [method cget] instance methods.
683 An option cannot be both locally defined and delegated.
685 TBD: Continue from here.
687 [call [cmd component] [arg comp] \
688 [opt "[const -public] [arg method]"] \
689 [opt "[const -inherit] [arg flag]"]]
691 Explicitly declares a component called [arg comp], and automatically
692 defines the component's instance variable.
696 If the [const -public] option is specified, then the option is made
697 public by defining a [arg method] whose subcommands are delegated
698 to the component e.g., specifying [const "-public mycomp"] is
699 equivalent to the following:
701 [example { component mycomp
702 delegate method {mymethod *} to mycomp
705 If the [const -inherit] option is specified, then [arg flag] must be a
706 Boolean value; if [arg flag] is true then all unknown methods and
707 options will be delegated to this component. The name [const -inherit]
708 implies that instances of this new type inherit, in a sense, the
709 methods and options of the component. That is, [const "-inherit yes"] is
712 [example { component mycomp
713 delegate option * to mycomp
714 delegate method * to mycomp
717 [call [cmd delegate] [const typemethod] [arg name] [const to] [arg comp] [opt "[const as] [arg target]"]]
719 Delegates type method [arg name] to type component [arg comp]. That is, when
720 type method [arg name] is called on this type, the type method
721 and its arguments will be passed to the named type component's command
722 instead. That is, the following statement
724 [example { delegate typemethod lostdogs to pound
727 is roughly equivalent to this explicitly defined method:
729 [example { typemethod lostdogs {args} {
730 uplevel $pound lostdogs $args
734 As with type methods, the [arg name] may have multiple tokens; in this
735 case, the last token of the name is assumed to be the name of the
740 The optional [const as] clause allows you to specify the delegated
741 method name and possibly add some arguments:
743 [example { delegate typemethod lostdogs to pound as "get lostdogs"
748 A type method cannot be both locally defined and delegated.
750 [call [cmd delegate] [const typemethod] [arg name] [opt "[const to] [arg comp]"] [const using] [arg pattern]]
752 In this form of the [cmd delegate] statement, the [const using] clause
753 is used to specify the precise form of the command to which type method
754 [arg name] name is delegated. In this form, the [const "to"] clause is
755 optional, since the chosen command might not involve any particular
760 The value of the [const using] clause is a list that may contain
761 any or all of the following substitution codes; these codes are
762 substituted with the described value to build the delegated command
763 prefix. Note that the following two statements are equivalent:
765 [example { delegate typemethod lostdogs to pound
766 delegate typemethod lostdogs to pound using "%c %m"
769 Each element of the list becomes a single element of the delegated
770 command--it is never reparsed as a string.
775 [list_begin definitions]
778 This is replaced with a single "%". Thus, to pass the string "%c"
779 to the command as an argument, you'd write "%%c".
783 This is replaced with the named type component's command.
787 This is replaced with the final token of the type method [arg name]; if
788 the type method [arg name] has one token, this is identical to [const %M].
792 This is replaced by the type method [arg name]; if the [arg name] consists
793 of multiple tokens, they are joined by space characters.
797 This is replaced by the type method [arg name]; if the [arg name] consists
798 of multiple tokens, they are joined by underscores ("_").
802 This is replaced with the fully qualified type name.
806 [call [cmd delegate] [const typemethod] [const *] [opt "[const to] [arg comp]"] \
807 [opt "[const using] [arg pattern]"] [opt "[const except] [arg exceptions]"]]
809 The form [cmd "delegate typemethod *"] delegates all unknown type
811 specified type component. The [const except] clause can be used to
812 specify a list of [arg exceptions], i.e., type method names that will not
813 be so delegated. The [const using] clause is defined as given above.
814 In this form, the statement must contain the [const to] clause, the
815 [const using] clause, or both.
819 [const Note:] By default, Snit interprets [cmd "\$type foo"], where
821 not a defined type method, as equivalent to [cmd "\$type create foo"], where
822 [const "foo"] is the name of a new instance of the type. If you
823 use [const "delegate typemethod *"], then the [method "create"] type
824 method must always be used explicitly.
828 The "*" can be a list of two or more tokens whose last
829 element is "*", as in the following example:
831 [example { delegate typemethod {tail *} to tail
834 This implicitly defines the type method [cmd tail] whose subcommands will
835 be delegated to the [var tail] type component.
837 [call [cmd typecomponent] [arg comp] \
838 [opt "[const -public] [arg typemethod]"] \
839 [opt "[const -inherit] [arg flag]"]]
841 Explicitly declares a type component called [arg comp], and automatically
842 defines the component's type variable. A type component is an arbitrary
843 command to which type methods and instance methods can be delegated;
844 the command's name is stored in a type variable.
848 If the [const -public] option is specified, then the type component is made
849 public by defining a [arg typemethod] whose subcommands are delegated to
850 the type component, e.g., specifying [const "-public mytypemethod"]
851 is equivalent to the following:
853 [example { typecomponent mycomp
854 delegate typemethod {mytypemethod *} to mycomp
857 If the [const -inherit] option is specified, then [arg flag] must be a
858 Boolean value; if [arg flag] is true then all unknown type methods
859 will be delegated to this type component. (See the note on "delegate
860 typemethod *", above.) The name [const -inherit]
861 implies that this type inherits, in a sense, the behavior of
862 the type component. That is, [const "-inherit yes"] is equivalent to:
864 [example { typecomponent mycomp
865 delegate typemethod * to mycomp
868 [call [cmd pragma] [opt [arg options...]]]
870 The [cmd pragma] statement provides control over how Snit generates a
871 type. It takes the following options; in each case, [arg flag] must
872 be a Boolean value recognized by Tcl, e.g., [const 0], [const 1],
873 [const "yes"], [const "no"], and so
878 By setting the [const -hastypeinfo], [const -hastypedestroy], and
879 [const -hasinstances] pragmas to false and defining appropriate
880 type methods, you can create an ensemble command without any extraneous
883 [list_begin definitions]
884 [def "[const -canreplace] [arg flag]"]
886 If false (the default) Snit will not create an instance of a
887 [cmd snit::type] that has the same name as an existing command; this
888 prevents subtle errors. Setting this pragma to true restores the
889 behavior of Snit V0.93 and earlier versions.
891 [def "[const -hastypeinfo] [arg flag]"]
893 If true (the default), the generated type will have a type method
894 called [cmd info] that is used for type introspection; the [cmd info]
895 type method is documented below. If false, it will not.
897 [def "[const -hastypedestroy] [arg flag]"]
899 If true (the default), the generated type will have a type method
900 called [cmd destroy] that is used to destroy the type and all of its
901 instances. The [cmd destroy] type method is documented below. If
904 [def "[const -hastypemethods] [arg flag]"]
906 If true (the default), the generated type's type command will have
907 subcommands (type methods) as usual. If false, the type command
908 will serve only to create instances of the type; the first argument
909 is the instance name.
913 This pragma and [const -hasinstances] cannot both be set false.
915 [def "[const -hasinstances] [arg flag]"]
917 If true (the default), the generated type will have a type method
918 called [cmd create] that is used to create instances of the type,
919 along with a variety of instance-related features. If false, it will
924 This pragma and [const -hastypemethods] cannot both be set false.
926 [def "[const -hasinfo] [arg flag]"]
928 If true (the default), instances of the generated type will have
929 an instance method called [method info] that is used for
930 instance introspection; the [method info]
931 method is documented below. If false, it will not.
933 [def "[const -simpledispatch] [arg flag]"]
935 This pragma is intended to make simple, heavily-used abstract
936 data types (e.g., stacks and queues) more efficient.
940 If false (the default), instance methods are dispatched normally. If
941 true, a faster dispatching scheme is used instead.
942 The speed comes at a price; with [const "-simpledispatch yes"] you
943 get the following limitations:
945 [list_begin itemized]
947 [item] Methods cannot be delegated.
948 [item] [cmd uplevel] and [cmd upvar] do not work as expected: the
949 caller's scope is two levels up rather than one.
950 [item] The option-handling methods
951 ([cmd cget], [cmd configure], and [cmd configurelist]) are very
957 [call [cmd expose] [arg comp]]
958 [call [cmd expose] [arg comp] [const as] [arg method]]
961 The word "Deprecated" really needs to be boldface, and
962 there's no good way to do it, so I'm using "const".
965 [const Deprecated.] To expose component [arg comp] publicly, use
966 [cmd component]'s [const -public] option.
968 [call [cmd onconfigure] [arg name] [arg arglist] [arg body]]
970 [const Deprecated.] Define [cmd option]'s [const -configuremethod]
975 As of version 0.95, the following definitions,
977 [example { option -myoption
978 onconfigure -myoption {value} {
979 # Code to save the option's value
983 are implemented as follows:
985 [example { option -myoption -configuremethod _configure-myoption
986 method _configure-myoption {_option value} {
987 # Code to save the option's value
991 [call [cmd oncget] [arg name] [arg body]]
993 [const Deprecated.] Define [cmd option]'s [const -cgetmethod]
998 As of version 0.95, the following definitions,
1000 [example { option -myoption
1002 # Code to return the option's value
1006 are implemented as follows:
1008 [example { option -myoption -cgetmethod _cget-myoption
1009 method _cget-myoption {_option} {
1010 # Code to return the option's value
1017 [call [cmd snit::widget] [arg name] [arg definition]]
1019 This command defines a Snit megawidget type with the specified
1020 [arg name]. The [arg definition] is defined as for [cmd snit::type].
1021 A [cmd snit::widget] differs from a [cmd snit::type]
1024 [list_begin itemized]
1027 Every instance of a [cmd snit::widget] has an automatically-created
1028 component called [var hull], which is normally a Tk frame widget.
1029 Other widgets created as part of the megawidget will be created within
1034 The hull component is initially created with the requested widget
1035 name; then Snit does some magic, renaming the hull component and
1036 installing its own instance command in its place.
1038 The hull component's new name is saved in an instance variable called
1043 The name of an instance must be valid Tk window name, and the parent
1048 A [cmd snit::widget] definition can include any of statements allowed
1049 in a [cmd snit::type] definition, and may also include the following:
1051 [list_begin definitions]
1053 [call [cmd widgetclass] [arg name]]
1055 Sets the [cmd snit::widget]'s widget class to [arg name], overriding
1056 the default. See [sectref {The Tk Option Database}] for more
1059 [call [cmd hulltype] [arg type]]
1061 Determines the kind of widget used as the [cmd snit::widget]'s hull.
1062 The [arg type] may be [const frame] (the default), [const toplevel],
1063 [const labelframe]; the qualified equivalents of these,
1064 [const tk::frame], [const tk::toplevel], and [const tk::labelframe];
1065 or, if available, the equivalent Tile widgets:
1066 [const ttk::frame], [const ttk::toplevel], and
1067 [const ttk::labelframe]. In practice, any widget that supports the
1068 [const -class] option can be used as a hull widget by
1069 [cmd lappend]'ing its name to the variable [var snit::hulltypes].
1073 [call [cmd snit::widgetadaptor] [arg name] [arg definition]]
1075 This command defines a Snit megawidget type with the specified name.
1076 It differs from [cmd snit::widget] in that the instance's [var hull]
1077 component is not created automatically, but is created in the
1078 constructor and installed using the [cmd installhull] command. Once
1079 the hull is installed, its instance command is renamed and replaced as
1080 with normal [cmd snit::widget]s. The original command is again
1081 accessible in the instance variable [var hull].
1085 Note that in general it is not possible to change the
1086 [emph {widget class}] of a [cmd snit::widgetadaptor]'s hull widget.
1090 See [sectref {The Tk Option Database}] for information on how
1091 [cmd snit::widgetadaptor]s interact with the option database.
1093 [call [cmd snit::typemethod] [arg type] [arg name] [arg arglist] [arg body]]
1095 Defines a new type method (or redefines an existing type method)
1096 for a previously existing [arg type].
1098 [call [cmd snit::method] [arg type] [arg name] [arg arglist] [arg body]]
1100 Defines a new instance method (or redefines an existing instance
1101 method) for a previously existing [arg type]. Note that delegated
1102 instance methods can't be redefined.
1104 [call [cmd snit::macro] [arg name] [arg arglist] [arg body]]
1106 Defines a Snit macro with the specified [arg name], [arg arglist], and
1107 [arg body]. Macros are used to define new type and widget
1108 definition statements in terms of the statements defined in this man
1113 A macro is simply a Tcl proc that is defined in the slave interpreter
1114 used to compile type and widget definitions. Thus, macros have
1115 access to all of the type and widget definition statements. See
1116 [sectref "Macros and Meta-programming"] for more details.
1120 The macro [arg name] cannot be the same as any standard Tcl command,
1121 or any Snit type or widget definition statement, e.g., you can't
1122 redefine the [cmd method] or [cmd delegate] statements, or the
1123 standard [cmd set], [cmd list], or [cmd string] commands.
1125 [call [cmd snit::compile] [arg which] [arg type] [arg body]]
1127 Snit defines a type, widget, or widgetadaptor by "compiling" the
1128 definition into a Tcl script; this script is then evaluated in the
1129 Tcl interpreter, which actually defines the new type.
1133 This command exposes the "compiler". Given a definition [arg body]
1134 for the named [arg type], where [arg which] is [const type],
1135 [const widget], or [const widgetadaptor], [cmd snit::compile] returns a list
1136 of two elements. The first element is the fully qualified type name;
1137 the second element is the definition script.
1141 [cmd snit::compile] is useful when additional processing
1142 must be done on the Snit-generated code--if it must be instrumented,
1143 for example, or run through the TclDevKit compiler. In addition, the
1144 returned script could be saved in a ".tcl" file and used to define the
1145 type as part of an application or library, thus saving the compilation
1146 overhead at application start-up. Note that the
1147 same version of Snit must be used at run-time as at compile-time.
1151 [subsection {The Type Command}]
1153 A type or widget definition creates a type command, which is used to
1154 create instances of the type. The type command has this form:
1157 [list_begin definitions]
1158 [call [cmd {$type}] [arg typemethod] [arg args]...]
1160 The [arg typemethod] can be any of the
1161 [sectref "Standard Type Methods"] (e.g., [method create]),
1162 or any type method defined in the type
1165 The subsequent [arg args] depend on the specific [arg typemethod]
1170 The type command is most often used to create new instances of the
1171 type; hence, the [method create] method is assumed if the first
1172 argument to the type command doesn't name a valid type method, unless
1173 the type definition includes [cmd "delegate typemethod *"] or the
1174 [const -hasinstances] pragma is set to false.
1178 Furthermore, if the [const -hastypemethods] pragma is false, then
1179 Snit type commands can be called with no arguments at
1180 all; in this case, the type command creates an instance with an
1181 automatically generated name. In other words, provided that the
1182 [const -hastypemethods] pragma is false and the type
1183 has instances, the following commands are equivalent:
1185 [example {snit::type dog { ... }
1187 set mydog [dog create %AUTO%]
1188 set mydog [dog %AUTO%]
1192 This doesn't work for Snit widgets, for obvious reasons.
1196 [emph "Snit 1.x Incompatibility:"] In Snit 1.x, the above behavior is
1197 available whether [const -hastypemethods] is true (the default) or false.
1201 [subsection {Standard Type Methods}]
1203 In addition to any type methods in the type's definition, all type and
1204 widget commands will usually have at least the following subcommands:
1208 [list_begin definitions]
1210 [call [cmd {$type}] [method create] [arg name] [opt "[arg option] [arg value] ..."]]
1212 Creates a new instance of the type, giving it the specified [arg name]
1213 and calling the type's constructor.
1217 For [cmd snit::type]s, if [arg name] is not a fully-qualified command
1218 name, it is assumed to be a name in the namespace in which the call to
1219 [cmd snit::type] appears. The method returns the fully-qualified
1224 For [cmd snit::widget]s and [cmd snit::widgetadaptor]s, [arg name]
1225 must be a valid widget name; the method returns the widget name.
1229 So long as [arg name] does not conflict with any defined type method
1230 name the [method create] keyword may be omitted, unless
1231 the type definition includes [cmd "delegate typemethod *"] or the
1232 [const -hasinstances] pragma is set to false.
1236 If the [arg name] includes the string [const %AUTO%], it will be
1237 replaced with the string [const {$type$counter}] where [const {$type}] is
1238 the type name and [const {$counter}] is a counter that increments each
1239 time [const %AUTO%] is used for this type.
1243 By default, any arguments following the [arg name] will be a list of
1244 [arg option] names and their [arg value]s; however, a type's
1245 constructor can specify a different argument list.
1249 As of Snit V0.95, [method create] will throw an error if the [arg name]
1250 is the same as any existing command--note that this was always true
1251 for [cmd snit::widget]s and [cmd snit::widgetadaptor]s. You can
1252 restore the previous behavior using the [const -canreplace] pragma.
1255 [call [cmd {$type}] [method {info typevars}] [opt [arg pattern]]]
1257 Returns a list of the type's type variables (excluding Snit internal
1258 variables); all variable names are fully-qualified.
1262 If [arg pattern] is given, it's used as a [cmd {string match}]
1263 pattern; only names that match the pattern are returned.
1266 [call [cmd {$type}] [method {info typemethods}] [opt [arg pattern]]]
1268 Returns a list of the names of the type's type methods.
1269 If the type has hierarchical
1270 type methods, whether locally-defined or delegated, only the first
1271 word of each will be included in the list.
1276 definition includes [cmd "delegate typemethod *"], the list will
1277 include only the names of those implicitly delegated type methods
1278 that have been called at least once and are still in the type method cache.
1282 If [arg pattern] is given, it's used as a [cmd {string match}]
1283 pattern; only names that match the pattern are returned.
1286 [call [cmd {$type}] [method {info args}] [arg method]]
1288 Returns a list containing the names of the arguments to the type's
1289 [arg method], in order. This method cannot be applied to delegated
1293 [call [cmd {$type}] [method {info body}] [arg method]]
1295 Returns the body of typemethod [arg method]. This method cannot be
1296 applied to delegated type methods.
1299 [call [cmd {$type}] [method {info default}] [arg method] [arg aname] [arg varname]]
1301 Returns a boolean value indicating whether the argument [arg aname] of
1302 the type's [arg method] has a default value ([const true]) or not
1303 ([const false]). If the argument has a default its value is placed into
1304 the variable [arg varname].
1307 [call [cmd {$type}] [method {info instances}] [opt [arg pattern]]]
1309 Returns a list of the type's instances. For [cmd snit::type]s, it
1310 will be a list of fully-qualified instance names;
1311 for [cmd snit::widget]s, it will be a list of Tk widget names.
1315 If [arg pattern] is given, it's used as a [cmd {string match}]
1316 pattern; only names that match the pattern are returned.
1320 [emph "Snit 1.x Incompatibility:"] In Snit 1.x, the full multi-word
1321 names of hierarchical type methods are included in the return value.
1323 [call [cmd {$type}] [method destroy]]
1325 Destroys the type's instances, the type's namespace, and the type
1330 [subsection {The Instance Command}]
1332 A Snit type or widget's [method create] type method creates objects of
1333 the type; each object has a unique name that is also a Tcl command.
1334 This command is used to access the object's methods and data, and has
1339 [list_begin definitions]
1340 [call [cmd {$object}] [arg method] [arg args...]]
1342 The [arg method] can be any of the
1343 [sectref "Standard Instance Methods"], or any instance method
1344 defined in the type definition.
1346 The subsequent [arg args] depend on the specific [arg method] chosen.
1350 [subsection {Standard Instance Methods}]
1352 In addition to any delegated or locally-defined instance methods in
1353 the type's definition, all Snit objects will have at least the
1354 following subcommands:
1358 [list_begin definitions]
1359 [call [cmd {$object}] [method configure] [opt [arg option]] [opt [arg value]] ...]
1361 Assigns new values to one or more options. If called with one
1362 argument, an [arg option] name, returns a list describing the option,
1363 as Tk widgets do; if called with no arguments, returns a list of lists
1364 describing all options, as Tk widgets do.
1368 Warning: This information will be available for delegated options only
1369 if the component to which they are delegated has a [method configure]
1370 method that returns this same kind of information.
1374 Note: Snit defines this method only if the type has at least one
1377 [call [cmd {$object}] [method configurelist] [arg optionlist]]
1379 Like [method configure], but takes one argument, a list of options and
1380 their values. It's mostly useful in the type constructor, but can be
1385 Note: Snit defines this method only if the type has at least one
1388 [call [cmd {$object}] [method cget] [arg option]]
1390 Returns the option's value.
1394 Note: Snit defines this method only if the type has at least one
1397 [call [cmd {$object}] [method destroy]]
1399 Destroys the object, calling the [cmd destructor] and freeing all
1406 The [method destroy] method isn't defined for [cmd snit::widget] or
1407 [cmd snit::widgetadaptor] objects; instances of these are destroyed by
1408 calling [package Tk]'s [cmd destroy] command, just as normal
1412 [call [cmd {$object}] [method {info type}]]
1414 Returns the instance's type.
1417 [call [cmd {$object}] [method {info vars}] [opt [arg pattern]]]
1419 Returns a list of the object's instance variables (excluding Snit
1420 internal variables). The names are fully qualified.
1424 If [arg pattern] is given, it's used as a [cmd {string match}]
1425 pattern; only names that match the pattern are returned.
1428 [call [cmd {$object}] [method {info typevars}] [opt [arg pattern]]]
1430 Returns a list of the object's type's type variables (excluding Snit
1431 internal variables). The names are fully qualified.
1435 If [arg pattern] is given, it's used as a [cmd {string match}]
1436 pattern; only names that match the pattern are returned.
1439 [call [cmd {$object}] [method {info typemethods}] [opt [arg pattern]]]
1441 Returns a list of the names of the type's type methods.
1442 If the type has hierarchical
1443 type methods, whether locally-defined or delegated, only the first
1444 word of each will be included in the list.
1449 definition includes [cmd "delegate typemethod *"], the list will
1450 include only the names of those implicitly delegated type methods
1451 that have been called at least once and are still in the type method cache.
1455 If [arg pattern] is given, it's used as a [cmd {string match}]
1456 pattern; only names that match the pattern are returned.
1460 [emph "Snit 1.x Incompatibility:"] In Snit 1.x, the full multi-word
1461 names of hierarchical type methods are included in the return value.
1463 [call [cmd {$object}] [method {info options}] [opt [arg pattern]]]
1465 Returns a list of the object's option names. This always includes
1466 local options and explicitly delegated options. If unknown options
1467 are delegated as well, and if the component to which they are
1468 delegated responds to [cmd {$object configure}] like Tk widgets do,
1469 then the result will include all possible unknown options that can
1470 be delegated to the component.
1474 If [arg pattern] is given, it's used as a [cmd {string match}]
1475 pattern; only names that match the pattern are returned.
1479 Note that the return value might be different for different instances
1480 of the same type, if component object types can vary from one instance
1483 [call [cmd {$object}] [method {info methods}] [opt [arg pattern]]]
1485 Returns a list of the names of the instance's methods.
1486 If the type has hierarchical methods, whether locally-defined or
1487 delegated, only the first word of each will be included in the list.
1492 definition includes [cmd "delegate method *"], the list will
1493 include only the names of those implicitly delegated methods that have
1494 been called at least once and are still in the method cache.
1498 If [arg pattern] is given, it's used as a [cmd {string match}]
1499 pattern; only names that match the pattern are returned.
1503 [emph "Snit 1.x Incompatibility:"] In Snit 1.x, the full multi-word
1504 names of hierarchical type methods are included in the return value.
1507 [call [cmd {$object}] [method {info args}] [arg method]]
1509 Returns a list containing the names of the arguments to the instance's
1510 [arg method], in order. This method cannot be applied to delegated methods.
1513 [call [cmd {$object}] [method {info body}] [arg method]]
1515 Returns the body of the instance's method [arg method]. This method
1516 cannot be applied to delegated methods.
1519 [call [cmd {$object}] [method {info default}] [arg method] [arg aname] [arg varname]]
1521 Returns a boolean value indicating whether the argument [arg aname] of
1522 the instance's [arg method] has a default value ([const true]) or not
1523 ([const false]). If the argument has a default its value is placed into
1524 the variable [arg varname].
1529 [subsection {Commands for use in Object Code}]
1531 Snit defines the following commands for use in your object code:
1532 that is, for use in type methods, instance methods, constructors,
1533 destructors, onconfigure handlers, oncget handlers, and procs.
1534 They do not reside in the ::snit:: namespace; instead, they are
1535 created with the type, and can be used without qualification.
1538 [list_begin definitions]
1540 [call [cmd mymethod] [arg name] [opt [arg args...]]]
1542 The [cmd mymethod] command is used for formatting callback commands to
1543 be passed to other objects. It returns a command that when called
1544 will invoke method [arg name] with the specified arguments, plus of
1545 course any arguments added by the caller. In other words, both of the
1546 following commands will cause the object's
1547 [method dosomething] method to be called when the [cmd {$button}] is pressed:
1549 [example { $button configure -command [list $self dosomething myargument]
1551 $button configure -command [mymethod dosomething myargument]
1554 The chief distinction between the two is that the latter form will not
1555 break if the object's command is renamed.
1557 [call [cmd mytypemethod] [arg name] [opt [arg args...]]]
1559 The [cmd mytypemethod] command is used for formatting callback commands to
1560 be passed to other objects. It returns a command that when called
1561 will invoke type method [arg name] with the specified arguments, plus of
1562 course any arguments added by the caller. In other words, both of the
1563 following commands will cause the object's [method dosomething] type method
1564 to be called when [cmd {$button}] is pressed:
1566 [example { $button configure -command [list $type dosomething myargument]
1568 $button configure -command [mytypemethod dosomething myargument]
1571 Type commands cannot be renamed, so in practice there's little
1572 difference between the two forms. [cmd mytypemethod] is provided for
1573 parallelism with [cmd mymethod].
1575 [call [cmd myproc] [arg name] [opt [arg args...]]]
1577 The [cmd myproc] command is used for formatting callback commands to
1578 be passed to other objects. It returns a command that when called
1579 will invoke the type proc [arg name] with the specified arguments, plus of
1580 course any arguments added by the caller. In other words, both of the
1581 following commands will cause the object's [method dosomething] proc
1582 to be called when [cmd {$button}] is pressed:
1584 [example { $button configure -command [list ${type}::dosomething myargument]
1586 $button configure -command [myproc dosomething myargument]
1589 [call [cmd myvar] [arg name]]
1591 Given an instance variable name, returns the fully qualified name.
1592 Use this if you're passing the variable to some other object, e.g., as
1593 a [option -textvariable] to a Tk label widget.
1595 [call [cmd mytypevar] [arg name]]
1597 Given an type variable name, returns the fully qualified name. Use
1598 this if you're passing the variable to some other object, e.g., as a
1599 [option -textvariable] to a Tk label widget.
1601 [call [cmd from] [arg argvName] [arg option] [opt [arg defvalue]]]
1603 The [cmd from] command plucks an option value from a list of options
1604 and their values, such as is passed into a type's [cmd constructor].
1605 [arg argvName] must be the name of a variable containing such a list;
1606 [arg option] is the name of the specific option.
1610 [cmd from] looks for [arg option] in the option list. If it is found,
1611 it and its value are removed from the list, and the value is returned.
1612 If [arg option] doesn't appear in the list, then the [arg defvalue] is
1615 If the option is locally-defined option, and [arg defvalue] is
1616 not specified, then the option's default value as specified in the
1617 type definition will be returned instead.
1619 [call [cmd install] [arg compName] [const using] [arg objType] [arg objName] [arg args...]]
1621 Creates a new object of type [arg objType] called [arg objName]
1622 and installs it as component [arg compName],
1623 as described in [sectref {Components and Delegation}]. Any additional
1624 [arg args...] are passed along with the name to the [arg objType]
1627 If this is a [cmd snit::type], then the following two commands are
1630 [example { install myComp using myObjType $self.myComp args...
1632 set myComp [myObjType $self.myComp args...]
1635 Note that whichever method is used, [arg compName] must still be
1636 declared in the type definition using [cmd component], or must be
1637 referenced in at least one [cmd delegate] statement.
1641 If this is a [cmd snit::widget] or [cmd snit::widgetadaptor], and if
1642 options have been delegated to component [arg compName], then those
1643 options will receive default values from the Tk option database. Note
1644 that it doesn't matter whether the component to be installed is a
1645 widget or not. See [sectref {The Tk Option Database}] for more
1650 [cmd install] cannot be used to install type components; just assign
1651 the type component's command name to the type component's variable
1654 [call [cmd installhull] [const using] [arg widgetType] [arg args...]]
1655 [call [cmd installhull] [arg name]]
1657 The constructor of a [cmd snit::widgetadaptor] must create a widget to
1658 be the object's hull component; the widget is installed as the hull
1659 component using this command. Note that the installed widget's name
1660 must be [const {$win}].
1662 This command has two forms.
1666 The first form specifies the [arg widgetType] and the [arg args...]
1667 (that is, the hardcoded option list) to use in creating the hull.
1668 Given this form, [cmd installhull] creates the hull widget, and
1669 initializes any options delegated to the hull from the Tk option
1674 In the second form, the hull widget has already been created; note
1675 that its name must be "$win". In this case, the Tk option database is
1676 [emph not] queried for any options delegated to the hull.
1678 The longer form is preferred; however, the shorter form allows the
1679 programmer to adapt a widget created elsewhere, which is sometimes
1680 useful. For example, it can be used to adapt a "page" widget created
1681 by a [package BWidgets] tabbed notebook or pages manager widget.
1685 See [sectref {The Tk Option Database}] for more information
1686 about [cmd snit::widgetadaptor]s and the option database.
1688 [call [cmd variable] [arg name]]
1690 Normally, instance variables are defined in the type definition along
1691 with the options, methods, and so forth; such instance variables are
1692 automatically visible in all instance code (e.g., method bodies). However,
1693 instance code can use the [cmd variable] command to declare instance variables
1694 that don't appear in the type definition, and also to bring variables
1695 from other namespaces into scope in the usual way.
1699 It's generally clearest to define all instance variables in the type
1700 definition, and omit declaring them in methods and so forth.
1704 Note that this is an instance-specific version of the standard Tcl
1705 [cmd ::variable] command.
1707 [call [cmd typevariable] [arg name]]
1709 Normally, type variables are defined in the type definition, along
1710 with the instance variables; such type variables are automatically
1711 visible in all of the type's code. However, type methods, instance
1712 methods and so forth can use [cmd typevariable] to declare type
1713 variables that don't appear in the type definition.
1717 It's generally clearest to declare all type variables in the type
1718 definition, and omit declaring them in methods, type methods, etc.
1720 [call [cmd varname] [arg name]]
1722 [const Deprecated.] Use [cmd myvar] instead.
1726 Given an instance variable name, returns the fully qualified name.
1727 Use this if you're passing the variable to some other object, e.g., as
1728 a [option -textvariable] to a Tk label widget.
1731 [call [cmd typevarname] [arg name]]
1733 [const Deprecated.] Use [cmd mytypevar] instead.
1737 Given a type variable name, returns the fully qualified name. Use
1738 this if you're passing the type variable to some other object, e.g., as a
1739 [option -textvariable] to a Tk label widget.
1741 [call [cmd codename] [arg name]]
1743 [const Deprecated.] Use [cmd myproc] instead.
1745 Given the name of a proc (but not a type or instance method), returns
1746 the fully-qualified command name, suitable for passing as a callback.
1751 [subsection {Components and Delegation}]
1753 When an object includes other objects, as when a toolbar contains
1754 buttons or a GUI object contains an object that references a database,
1755 the included object is called a component. The standard way to handle
1756 component objects owned by a Snit object is to declare them using
1757 [cmd component], which creates a component instance variable.
1758 In the following example, a [cmd dog] object has a
1762 [example { snit::type dog {
1765 constructor {args} {
1766 set mytail [tail %AUTO% -partof $self]
1767 $self configurelist $args
1778 method wag {} { return "Wag, wag, wag."}
1783 Because the [cmd tail] object's name is stored in an instance
1784 variable, it's easily accessible in any method.
1788 The [cmd install] command provides an alternate way
1789 to create and install the component:
1792 [example { snit::type dog {
1795 constructor {args} {
1796 install mytail using tail %AUTO% -partof $self
1797 $self configurelist $args
1807 For [cmd snit::type]s, the two methods are equivalent; for
1808 [cmd snit::widget]s and [cmd snit::widgetadaptor]s, the [cmd install]
1809 command properly initializes the widget's options by querying
1810 [sectref {The Tk Option Database}].
1814 In the above examples, the [cmd dog] object's [method wag] method
1815 simply calls the [cmd tail] component's [method wag] method. In OO
1816 jargon, this is called delegation. Snit provides an easier way to do
1820 [example { snit::type dog {
1821 delegate method wag to mytail
1823 constructor {args} {
1824 install mytail using tail %AUTO% -partof $self
1825 $self configurelist $args
1831 The [cmd delegate] statement in the type definition implicitly defines
1832 the instance variable [var mytail] to hold the component's name
1833 (though it's good form to use [cmd component] to declare it explicitly); it
1834 also defines the [cmd dog] object's [method wag] method, delegating it
1835 to the [var mytail] component.
1839 If desired, all otherwise unknown methods can be delegated to a
1845 delegate method * to mytail
1847 constructor {args} {
1848 set mytail [tail %AUTO% -partof $self]
1849 $self configurelist $args
1852 method bark { return "Bark, bark, bark!" }
1857 In this case, a [cmd dog] object will handle its own [method bark]
1858 method; but [method wag] will be passed along to [cmd mytail]. Any
1859 other method, being recognized by neither [cmd dog] nor [cmd tail],
1860 will simply raise an error.
1864 Option delegation is similar to method delegation, except for the
1865 interactions with the Tk option database; this is described in
1866 [sectref "The Tk Option Database"].
1868 [subsection {Type Components and Delegation}]
1870 The relationship between type components and instance components is
1871 identical to that between type variables and instance variables, and
1872 that between type methods and instance methods. Just as an instance
1873 component is an instance variable that holds the name of a command, so
1874 a type component is a type variable that holds the name of a command.
1875 In essence, a type component is a component that's shared by every
1876 instance of the type.
1880 Just as [cmd "delegate method"] can be used to delegate methods to
1881 instance components, as described in
1882 [sectref "Components and Delegation"], so [cmd "delegate typemethod"]
1883 can be used to delegate type methods to type components.
1887 Note also that as of Snit 0.95 [cmd "delegate method"] can delegate
1888 methods to both instance components and type components.
1890 [subsection {The Tk Option Database}]
1892 This section describes how Snit interacts with the Tk option database,
1893 and assumes the reader has a working knowledge of the option database
1894 and its uses. The book [emph {Practical Programming in Tcl and Tk}]
1895 by Welch et al has a good introduction to the option database, as does
1896 [emph {Effective Tcl/Tk Programming}].
1900 Snit is implemented so that most of the time it will simply do the
1901 right thing with respect to the option database, provided that the
1902 widget developer does the right thing by Snit. The body of this
1903 section goes into great deal about what Snit requires. The following
1904 is a brief statement of the requirements, for reference.
1908 [list_begin itemized]
1911 If the [cmd snit::widget]'s default widget class is not what is desired, set it
1912 explicitly using [cmd widgetclass] in the widget definition.
1916 When defining or delegating options, specify the resource and class
1917 names explicitly when if the defaults aren't what you want.
1921 Use [cmd {installhull using}] to install the hull for
1922 [cmd snit::widgetadaptor]s.
1926 Use [cmd install] to install all other components.
1931 The interaction of Tk widgets with the option database is a complex
1932 thing; the interaction of Snit with the option database is even more
1933 so, and repays attention to detail.
1937 [const {Setting the widget class:}] Every Tk widget has a widget class.
1938 For Tk widgets, the widget class name is the just the widget type name
1939 with an initial capital letter, e.g., the widget class for
1940 [cmd button] widgets is "Button".
1944 Similarly, the widget class of a [cmd snit::widget] defaults to the
1945 unqualified type name with the first letter capitalized. For example,
1949 [example { snit::widget ::mylibrary::scrolledText { ... }}]
1952 is "ScrolledText". The widget class can also be set explicitly using
1953 the [cmd widgetclass] statement within the [cmd snit::widget]
1958 Any widget can be used as the [cmd hulltype] provided that it supports
1959 the [const -class] option for changing its widget class name. See
1960 the discussion of the [cmd hulltype] command, above. The user may pass
1961 [const -class] to the widget at instantion.
1965 The widget class of a [cmd snit::widgetadaptor] is just the widget
1966 class of its hull widget; this cannot be changed unless the hull
1967 widget supports [const -class], in which case it will
1968 usually make more sense to use [cmd snit::widget] rather than
1969 [cmd snit::widgetadaptor].
1973 [const {Setting option resource names and classes:}] In Tk, every
1974 option has three names: the option name, the resource name, and the
1975 class name. The option name begins with a hyphen and is all lowercase;
1976 it's used when creating widgets, and with the [cmd configure] and
1977 [cmd cget] commands.
1981 The resource and class names are used to initialize option default
1982 values by querying the Tk option database. The resource name is
1983 usually just the option name minus the hyphen, but may contain
1984 uppercase letters at word boundaries; the class name is usually just
1985 the resource name with an initial capital, but not always. For
1986 example, here are the option, resource, and class names for several
1987 [cmd text] widget options:
1990 [example { -background background Background
1991 -borderwidth borderWidth BorderWidth
1992 -insertborderwidth insertBorderWidth BorderWidth
1997 As is easily seen, sometimes the resource and class names can be
1998 inferred from the option name, but not always.
2002 Snit options also have a resource name and a class name. By default,
2003 these names follow the rule given above: the resource name is the
2004 option name without the hyphen, and the class name is the resource
2005 name with an initial capital. This is true for both locally-defined
2006 options and explicitly delegated options:
2009 [example { snit::widget mywidget {
2011 delegate option -borderwidth to hull
2012 delegate option * to text
2018 In this case, the widget class name is "Mywidget". The widget has the
2019 following options: [option -background], which is locally defined, and
2020 [option -borderwidth], which is explicitly delegated; all other widgets are
2021 delegated to a component called "text", which is probably a Tk
2023 [cmd text] widget. If so, [cmd mywidget] has all the same options as
2024 a [cmd text] widget. The option, resource, and class names are as
2028 [example { -background background Background
2029 -borderwidth borderwidth Borderwidth
2034 Note that the locally defined option, [option -background], happens to have
2035 the same three names as the standard Tk [option -background] option; and
2036 [option -pad], which is delegated implicitly to the [var text]
2038 same three names for [cmd mywidget] as it does for the [cmd text]
2039 widget. [option -borderwidth], on the other hand, has different resource and
2040 class names than usual, because the internal word "width" isn't
2041 capitalized. For consistency, it should be; this is done as follows:
2044 [example { snit::widget mywidget {
2046 delegate option {-borderwidth borderWidth} to hull
2047 delegate option * to text
2053 The class name will default to "BorderWidth", as expected.
2057 Suppose, however, that [cmd mywidget] also delegated
2059 [option -pady] to the hull. In this case, both the resource name and the
2060 class name must be specified explicitly:
2063 [example { snit::widget mywidget {
2065 delegate option {-borderwidth borderWidth} to hull
2066 delegate option {-padx padX Pad} to hull
2067 delegate option {-pady padY Pad} to hull
2068 delegate option * to text
2074 [const {Querying the option database:}] If you set your widgetclass and
2075 option names as described above, Snit will query the option database
2076 when each instance is created, and will generally do the right thing
2077 when it comes to querying the option database. The remainder of this
2078 section goes into the gory details.
2081 [const {Initializing locally defined options:}]
2083 When an instance of a snit::widget is created, its locally defined
2084 options are initialized as follows: each option's resource and class
2085 names are used to query the Tk option database. If the result is
2086 non-empty, it is used as the option's default; otherwise, the default
2087 hardcoded in the type definition is used. In either case, the default
2088 can be overridden by the caller. For example,
2091 [example { option add *Mywidget.texture pebbled
2093 snit::widget mywidget {
2094 option -texture smooth
2098 mywidget .mywidget -texture greasy
2102 Here, [option -texture] would normally default to "smooth", but because of
2103 the entry added to the option database it defaults to "pebbled".
2104 However, the caller has explicitly overridden the default, and so the
2105 new widget will be "greasy".
2108 [const {Initializing options delegated to the hull:}]
2110 A [cmd snit::widget]'s hull is a widget, and given that its class has
2111 been set it is expected to query the option database for itself. The
2112 only exception concerns options that are delegated to it with a
2113 different name. Consider the following code:
2116 [example { option add *Mywidget.borderWidth 5
2117 option add *Mywidget.relief sunken
2118 option add *Mywidget.hullbackground red
2119 option add *Mywidget.background green
2121 snit::widget mywidget {
2122 delegate option -borderwidth to hull
2123 delegate option -hullbackground to hull as -background
2124 delegate option * to hull
2130 set A [.mywidget cget -relief]
2131 set B [.mywidget cget -hullbackground]
2132 set C [.mywidget cget -background]
2133 set D [.mywidget cget -borderwidth]
2137 The question is, what are the values of variables A, B, C and D?
2141 The value of A is "sunken". The hull is a Tk frame that has been
2142 given the widget class "Mywidget"; it will automatically query the
2143 option database and pick up this value. Since the [option -relief]
2144 option is implicitly delegated to the hull, Snit takes no action.
2148 The value of B is "red". The hull will automatically pick up the
2149 value "green" for its [option -background] option, just as it picked up the
2150 [option -relief] value. However, Snit knows that
2151 [option -hullbackground] is mapped to
2152 the hull's [option -background] option; hence, it queries the option database
2153 for [option -hullbackground] and gets "red" and updates the hull
2158 The value of C is also "red", because [option -background] is implicitly
2159 delegated to the hull; thus, retrieving it is the same as retrieving
2160 [option -hullbackground]. Note that this case is unusual; in practice,
2161 [option -background] would probably be explicitly delegated to some other
2166 The value of D is "5", but not for the reason you think. Note that as
2167 it is defined above, the resource name for [option -borderwidth]
2168 defaults to "borderwidth", whereas the option database entry is
2169 "borderWidth". As with [option -relief], the hull picks up its
2170 own [option -borderwidth] option before Snit does anything. Because the
2171 option is delegated under its own name, Snit assumes that the correct
2172 thing has happened, and doesn't worry about it any further.
2176 For [cmd snit::widgetadaptor]s, the case is somewhat altered. Widget
2177 adaptors retain the widget class of their hull, and the hull is not
2178 created automatically by Snit. Instead, the [cmd snit::widgetadaptor]
2179 must call [cmd installhull] in its constructor. The normal way to do
2183 [example { snit::widgetadaptor mywidget {
2185 constructor {args} {
2187 installhull using text -foreground white
2195 In this case, the [cmd installhull] command will create the hull using
2196 a command like this:
2199 [example { set hull [text $win -foreground white]
2203 The hull is a [cmd text] widget, so its widget class is "Text". Just
2204 as with [cmd snit::widget] hulls, Snit assumes that it will pick up
2205 all of its normal option values automatically; options delegated from
2206 a different name are initialized from the option database in the same
2210 [const {Initializing options delegated to other components:}]
2212 Non-hull components are matched against the option database in two
2213 ways. First, a component widget remains a widget still, and therefore
2214 is initialized from the option database in the usual way.
2216 Second, the option database is queried for all options delegated to
2217 the component, and the component is initialized accordingly--provided
2218 that the [cmd install] command is used to create it.
2222 Before option database support was added to Snit, the usual way to
2223 create a component was to simply create it in the constructor and
2224 assign its command name to the component variable:
2227 [example { snit::widget mywidget {
2228 delegate option -background to myComp
2230 constructor {args} {
2231 set myComp [text $win.text -foreground black]
2237 The drawback of this method is that Snit has no opportunity to
2238 initialize the component properly. Hence, the following approach is
2242 [example { snit::widget mywidget {
2243 delegate option -background to myComp
2245 constructor {args} {
2246 install myComp using text $win.text -foreground black
2252 The [cmd install] command does the following:
2255 [list_begin itemized]
2258 Builds a list of the options explicitly included in the [cmd install]
2259 command -- in this case, [option -foreground].
2263 Queries the option database for all options delegated explicitly to
2264 the named component.
2268 Creates the component using the specified command, after inserting
2269 into it a list of options and values read from the option database.
2270 Thus, the explicitly included options ([option -foreground]) will override
2271 anything read from the option database.
2275 If the widget definition implicitly delegated options to the component
2276 using [cmd "delegate option *"], then Snit calls the newly created
2277 component's [cmd configure] method to receive a list of all of the
2278 component's options. From this Snit builds a list of options
2279 implicitly delegated to the component that were not explicitly
2280 included in the [cmd install] command. For all such options, Snit
2281 queries the option database and configures the component accordingly.
2286 [const {Non-widget components:}] The option database is never queried
2287 for [cmd snit::type]s, since it can only be queried given a Tk widget
2290 However, [cmd snit::widget]s can have non-widget components. And if
2291 options are delegated to those components, and if the [cmd install]
2292 command is used to install those components, then they will be
2293 initialized from the option database just as widget components are.
2297 [subsection {Macros and Meta-programming}]
2299 The [cmd snit::macro] command enables a certain amount of
2300 meta-programming with Snit classes. For example, suppose you like to
2301 define properties: instance variables that have set/get methods. Your
2302 code might look like this:
2304 [example { snit::type dog {
2311 method setmood {newmood} {
2317 That's nine lines of text per property. Or, you could define the
2318 following [cmd snit::macro]:
2320 [example { snit::macro property {name initValue} {
2321 variable $name $initValue
2323 method get$name {} "return $name"
2325 method set$name {value} "set $name \$value"
2329 Note that a [cmd snit::macro] is just a normal Tcl proc defined in
2330 the slave interpreter used to compile type and widget definitions; as
2331 a result, it has access to all the commands used to define types and
2336 Given this new macro, you can define a property in one line of code:
2338 [example { snit::type dog {
2343 Within a macro, the commands [cmd variable] and [cmd proc] refer to
2344 the Snit type-definition commands, not the standard Tcl commands. To
2345 get the standard Tcl commands, use [cmd _variable] and [cmd _proc].
2349 Because a single slave interpreter is used for compiling all Snit
2350 types and widgets in the application, there's the possibility of macro
2351 name collisions. If you're writing a reuseable package using Snit,
2352 and you use some [cmd snit::macro]s, define them in your package
2355 [example { snit::macro mypkg::property {name initValue} { ... }
2358 mypkg::property mood happy
2362 This leaves the global namespace open for application authors.
2366 [subsection "Validation Types"]
2368 A validation type is an object that can be used to validate
2369 Tcl values of a particular kind. For example,
2370 [cmd snit::integer] is used to validate that a Tcl value is
2375 Every validation type has a [method validate] method which is used to
2376 do the validation. This method must take a single argument, the value
2377 to be validated; further, it must do nothing if the value is valid,
2378 but throw an error if the value is invalid:
2380 [example { snit::integer validate 5 ;# Does nothing
2381 snit::integer validate 5.0 ;# Throws an error (not an integer!)
2386 The [method validate] method will always return the validated value on success,
2387 and throw the [cmd -errorcode] INVALID on error.
2391 Snit defines a family of validation types, all of which are
2392 implemented as [cmd snit::type]'s. They can be used as is;
2393 in addition, their instances serve as parameterized
2394 subtypes. For example, a probability is a number between 0.0 and 1.0
2397 [example { snit::double probability -min 0.0 -max 1.0
2400 The example above creates an instance of [cmd snit::double]--a
2401 validation subtype--called
2402 [cmd probability], which can be used to validate probability values:
2404 [example { probability validate 0.5 ;# Does nothing
2405 probability validate 7.9 ;# Throws an error
2408 Validation subtypes can be defined explicitly, as in the above
2409 example; when a locally-defined option's [const -type] is specified,
2410 they may also be created on the fly:
2412 [example { snit::enum ::dog::breed -values {mutt retriever sheepdog}
2415 # Define subtypes on the fly...
2416 option -breed -type {
2417 snit::enum -values {mutt retriever sheepdog}
2420 # Or use predefined subtypes...
2421 option -breed -type ::dog::breed
2427 Any object that has a [method validate] method with the semantics
2428 described above can be used as a validation type; see
2429 [sectref "Defining Validation Types"] for information on how to define
2434 Snit defines the following validation types:
2436 [list_begin definitions]
2438 [call [cmd snit::boolean] [const validate] [opt [arg value]]]
2439 [call [cmd snit::boolean] [arg name]]
2441 Validates Tcl boolean values: 1, 0, [const on], [const off],
2442 [const yes], [const no], [const true], [const false].
2443 It's possible to define subtypes--that is, instances--of
2444 [cmd snit::boolean], but as it has no options there's no reason to do
2447 [call [cmd snit::double] [const validate] [opt [arg value]]]
2448 [call [cmd snit::double] [arg name] [opt "[arg option] [arg value]..."]]
2450 Validates floating-point values. Subtypes may be created with the
2453 [list_begin definitions]
2455 [def "[const -min] [arg min]"]
2457 Specifies a floating-point minimum bound; a value is invalid if it is strictly
2458 less than [arg min].
2460 [def "[const -max] [arg max]"]
2462 Specifies a floating-point maximum bound; a value is invalid if it is strictly
2463 greater than [arg max].
2467 [call [cmd snit::enum] [const validate] [opt [arg value]]]
2468 [call [cmd snit::enum] [arg name] [opt "[arg option] [arg value]..."]]
2470 Validates that a value comes from an enumerated list. The base
2471 type is of little use by itself, as only subtypes actually have
2472 an enumerated list to validate against. Subtypes may be created
2473 with the following options:
2475 [list_begin definitions]
2477 [def "[const -values] [arg list]"]
2479 Specifies a list of valid values. A value is valid if and only if
2480 it's included in the list.
2484 [call [cmd snit::fpixels] [const validate] [opt [arg value]]]
2485 [call [cmd snit::fpixels] [arg name] [opt "[arg option] [arg value]..."]]
2487 [emph "Tk programs only."] Validates screen distances, in any of the
2488 forms accepted by [cmd "winfo fpixels"]. Subtypes may be created with the
2491 [list_begin definitions]
2493 [def "[const -min] [arg min]"]
2495 Specifies a minimum bound; a value is invalid if it is strictly
2496 less than [arg min]. The bound may be expressed in any of the
2497 forms accepted by [cmd "winfo fpixels"].
2499 [def "[const -max] [arg max]"]
2501 Specifies a maximum bound; a value is invalid if it is strictly
2502 greater than [arg max]. The bound may be expressed in any of the
2503 forms accepted by [cmd "winfo fpixels"].
2507 [call [cmd snit::integer] [const validate] [opt [arg value]]]
2508 [call [cmd snit::integer] [arg name] [opt "[arg option] [arg value]..."]]
2510 Validates integer values. Subtypes may be created with the
2513 [list_begin definitions]
2515 [def "[const -min] [arg min]"]
2517 Specifies an integer minimum bound; a value is invalid if it is strictly
2518 less than [arg min].
2520 [def "[const -max] [arg max]"]
2522 Specifies an integer maximum bound; a value is invalid if it is strictly
2523 greater than [arg max].
2527 [call [cmd snit::listtype] [const validate] [opt [arg value]]]
2528 [call [cmd snit::listtype] [arg name] [opt "[arg option] [arg value]..."]]
2530 Validates Tcl lists. Subtypes may be created with the
2533 [list_begin definitions]
2535 [def "[const -minlen] [arg min]"]
2537 Specifies a minimum list length; the value is invalid if it has
2538 fewer than [arg min] elements. Defaults to 0.
2540 [def "[const -maxlen] [arg max]"]
2542 Specifies a maximum list length; the value is invalid if it
2543 more than [arg max] elements.
2545 [def "[const -type] [arg type]"]
2547 Specifies the type of the list elements; [arg type] must be
2548 the name of a validation type or subtype. In the
2549 following example, the value of [const -numbers] must be a list
2552 [example { option -numbers -type {snit::listtype -type snit::integer}
2555 Note that this option doesn't support defining new validation subtypes
2556 on the fly; that is, the following code will not work (yet, anyway):
2558 [example { option -numbers -type {
2559 snit::listtype -type {snit::integer -min 5}
2563 Instead, define the subtype explicitly:
2565 [example { snit::integer gt4 -min 5
2568 option -numbers -type {snit::listtype -type gt4}
2575 [call [cmd snit::pixels] [const validate] [opt [arg value]]]
2576 [call [cmd snit::pixels] [arg name] [opt "[arg option] [arg value]..."]]
2578 [emph "Tk programs only."] Validates screen distances, in any of the
2579 forms accepted by [cmd "winfo pixels"]. Subtypes may be created with the
2582 [list_begin definitions]
2584 [def "[const -min] [arg min]"]
2586 Specifies a minimum bound; a value is invalid if it is strictly
2587 less than [arg min]. The bound may be expressed in any of the
2588 forms accepted by [cmd "winfo pixels"].
2590 [def "[const -max] [arg max]"]
2592 Specifies a maximum bound; a value is invalid if it is strictly
2593 greater than [arg max]. The bound may be expressed in any of the
2594 forms accepted by [cmd "winfo pixels"].
2599 [call [cmd snit::stringtype] [const validate] [opt [arg value]]]
2600 [call [cmd snit::stringtype] [arg name] [opt "[arg option] [arg value]..."]]
2602 Validates Tcl strings. The base type is of little use by itself,
2603 since very Tcl value is also a valid string. Subtypes may be created with the
2606 [list_begin definitions]
2608 [def "[const -minlen] [arg min]"]
2610 Specifies a minimum string length; the value is invalid if it has
2611 fewer than [arg min] characters. Defaults to 0.
2613 [def "[const -maxlen] [arg max]"]
2615 Specifies a maximum string length; the value is invalid if it has
2616 more than [arg max] characters.
2618 [def "[const -glob] [arg pattern]"]
2620 Specifies a [cmd "string match"] pattern; the value is invalid
2621 if it doesn't match the pattern.
2623 [def "[const -regexp] [arg regexp]"]
2625 Specifies a regular expression; the value is invalid if it doesn't
2626 match the regular expression.
2628 [def "[const -nocase] [arg flag]"]
2630 By default, both [const -glob] and [const -regexp] matches are
2631 case-sensitive. If [const -nocase] is set to true, then both
2632 [const -glob] and [const -regexp] matches are case-insensitive.
2636 [call [cmd snit::window] [const validate] [opt [arg value]]]
2637 [call [cmd snit::window] [arg name]]
2639 [emph "Tk programs only."] Validates Tk window names. The value must
2640 cause [cmd "winfo exists"] to return true; otherwise, the value is
2641 invalid. It's possible to define subtypes--that is, instances--of
2642 [cmd snit::window], but as it has no options at present there's no
2649 [subsection "Defining Validation Types"]
2651 There are three ways to define a new validation type: as a subtype of
2652 one of Snit's validation types, as a validation type command, and as
2653 a full-fledged validation type similar to those provided by Snit.
2654 Defining subtypes of Snit's validation types is described above,
2655 under [sectref "Validation Types"].
2659 The next simplest way to create a new validation type is as a
2660 validation type command. A validation type is simply an
2661 object that has a [method validate] method; the [method validate]
2662 method must take one argument, a value, return the value if it is
2663 valid, and throw an error with [cmd -errorcode] INVALID if the
2664 value is invalid. This can be done with a simple [cmd proc]. For
2665 example, the [cmd snit::boolean] validate type could have been
2666 implemented like this:
2668 [example { proc ::snit::boolean {"validate" value} {
2669 if {![string is boolean -strict $value]} {
2670 return -code error -errorcode INVALID \
2671 "invalid boolean \"$value\", should be one of: 1, 0, ..."
2678 A validation type defined in this way cannot be subtyped, of course;
2679 but for many applications this will be sufficient.
2683 Finally, one can define a full-fledged, subtype-able validation type
2684 as a [cmd snit::type]. Here's a skeleton to get you started:
2686 [example { snit::type myinteger {
2687 # First, define any options you'd like to use to define
2688 # subtypes. Give them defaults such that they won't take
2689 # effect if they aren't used, and marked them "read-only".
2690 # After all, you shouldn't be changing their values after
2691 # a subtype is defined.
2695 option -min -default "" -readonly 1
2696 option -max -default "" -readonly 1
2698 # Next, define a "validate" type method which should do the
2699 # validation in the basic case. This will allow the
2700 # type command to be used as a validation type.
2702 typemethod validate {value} {
2703 if {![string is integer -strict $value]} {
2704 return -code error -errorcode INVALID \
2705 "invalid value \"$value\", expected integer"
2711 # Next, the constructor should validate the subtype options,
2712 # if any. Since they are all readonly, we don't need to worry
2713 # about validating the options on change.
2715 constructor {args} {
2716 # FIRST, get the options
2717 $self configurelist $args
2719 # NEXT, validate them.
2721 # I'll leave this to your imagination.
2724 # Next, define a "validate" instance method; its job is to
2725 # validate values for subtypes.
2727 method validate {value} {
2728 # First, call the type method to do the basic validation.
2729 $type validate $value
2731 # Now we know it's a valid integer.
2733 if {("" != $options(-min) && $value < $options(-min)) ||
2734 ("" != $options(-max) && $value > $options(-max))} {
2735 # It's out of range; format a detailed message about
2736 # the error, and throw it.
2740 return -code error -errorcode INVALID $msg
2743 # Otherwise, if it's valid just return it.
2749 And now you have a type that can be subtyped.
2753 The file "validate.tcl" in the Snit distribution defines all of Snit's
2754 validation types; you can find the complete implementation for
2755 [cmd snit::integer] and the other types there, to use as examples for
2762 If you have problems, find bugs, or new ideas you are hereby cordially
2763 invited to submit a report of your problem, bug, or idea at the
2764 SourceForge trackers for tcllib, which can be found at
2766 [uri http://sourceforge.net/projects/tcllib/].
2768 The relevant category is [emph snit].
2772 Additionally, you might wish to join the Snit mailing list;
2773 see [uri http://www.wjduquette.com/snit] for details.
2777 One particular area to watch is using [cmd snit::widgetadaptor] to
2778 adapt megawidgets created by other megawidget packages; correct
2779 widget destruction depends on the order of the <Destroy> bindings.
2780 The wisest course is simply not to do this.
2782 [section {KNOWN BUGS}]
2784 [list_begin itemized]
2787 Error stack traces returned by Snit 1.x are extremely ugly and typically
2788 contain far too much information about Snit internals. The error
2789 messages are much improved in Snit 2.2.
2793 Also see the SourceForge Trackers at
2794 [uri http://sourceforge.net/projects/tcllib/], category [emph snit].
2801 During the course of developing Notebook
2802 (See [uri http://www.wjduquette.com/notebook]), my Tcl-based personal
2803 notebook application, I found I was writing it as a collection of
2804 objects. I wasn't using any particular object-oriented framework; I
2805 was just writing objects in pure Tcl following the guidelines in my
2806 Guide to Object Commands
2807 (see [uri http://www.wjduquette.com/tcl/objects.html]), along with a
2808 few other tricks I'd picked up since. And though it was working well,
2809 it quickly became tiresome because of the amount of boilerplate
2810 code associated with each new object type.
2814 So that was one thing--tedium is a powerful motivator. But the other
2815 thing I noticed is that I wasn't using inheritance at all, and I
2816 wasn't missing it. Instead, I was using delegation: objects that
2817 created other objects and delegated methods to them.
2821 And I said to myself, "This is getting tedious...there has got to be a
2822 better way." And one afternoon, on a whim, I started working on Snit,
2823 an object system that works the way Tcl works. Snit doesn't support
2824 inheritance, but it's great at delegation, and it makes creating
2829 If you have any comments or suggestions (or bug reports!) don't
2830 hesitate to send me e-mail at [uri will@wjduquette.com]. In addition,
2831 there's a Snit mailing list; you can find out more about it at the
2832 Snit home page (see [uri http://www.wjduquette.com/snit]).
2839 Snit has been designed and implemented from the very beginning by
2840 William H. Duquette. However, much credit belongs to the following
2841 people for using Snit and providing me with valuable feedback: Rolf
2842 Ade, Colin McCormack, Jose Nazario, Jeff Godfrey, Maurice Diamanti,
2843 Egon Pasztor, David S. Cargo, Tom Krehbiel, Michael Cleverly,
2844 Andreas Kupries, Marty Backe, Andy Goth, Jeff Hobbs, Brian
2845 Griffin, Donal Fellows, Miguel Sofer, Kenneth Green,
2846 and Anton Kovalenko.
2847 If I've forgotten anyone, my apologies; let me know and I'll add
2848 your name to the list.
2850 [section {BUGS, IDEAS, FEEDBACK}]
2852 This document, and the package it describes, will undoubtedly contain
2853 bugs and other problems.
2855 Please report such in the category [emph snit] of the
2856 [uri {http://sourceforge.net/tracker/?group_id=12883} {Tcllib SF Trackers}].
2858 Please also report any ideas for enhancements you may have for either
2859 package and/or documentation.
2862 [keywords class {object oriented} object C++]
2863 [keywords Snit type {Incr Tcl} BWidget]
2864 [keywords widget adaptors {widget adaptors} {mega widget}]