1snit(n) Snit's Not Incr Tcl, OO system snit(n)
2
3
4
5______________________________________________________________________________
6
8 snit - Snit's Not Incr Tcl
9
11 package require Tcl 8.5
12
13 package require snit ?2.1?
14
15 snit::type name definition
16
17 typevariable name ?-array? ?value?
18
19 typemethod name arglist body
20
21 typeconstructor body
22
23 variable name ?-array? ?value?
24
25 method name arglist body
26
27 option namespec ?defaultValue?
28
29 option namespec ?options...?
30
31 constructor arglist body
32
33 destructor body
34
35 proc name args body
36
37 delegate method name to comp ?as target?
38
39 delegate method name ?to comp? using pattern
40
41 delegate method * ?to comp? ?using pattern? ?except exceptions?
42
43 delegate option namespec to comp
44
45 delegate option namespec to comp as target
46
47 delegate option * to comp
48
49 delegate option * to comp except exceptions
50
51 component comp ?-public method? ?-inherit flag?
52
53 delegate typemethod name to comp ?as target?
54
55 delegate typemethod name ?to comp? using pattern
56
57 delegate typemethod * ?to comp? ?using pattern? ?except exceptions?
58
59 typecomponent comp ?-public typemethod? ?-inherit flag?
60
61 pragma ?options...?
62
63 expose comp
64
65 expose comp as method
66
67 onconfigure name arglist body
68
69 oncget name body
70
71 snit::widget name definition
72
73 widgetclass name
74
75 hulltype type
76
77 snit::widgetadaptor name definition
78
79 snit::typemethod type name arglist body
80
81 snit::method type name arglist body
82
83 snit::macro name arglist body
84
85 snit::compile which type body
86
87 $type typemethod args...
88
89 $type create name ?option value ...?
90
91 $type info typevars ?pattern?
92
93 $type info typemethods ?pattern?
94
95 $type info instances ?pattern?
96
97 $type destroy
98
99 $object method args...
100
101 $object configure ?option? ?value? ...
102
103 $object configurelist optionlist
104
105 $object cget option
106
107 $object destroy
108
109 $object info type
110
111 $object info vars ?pattern?
112
113 $object info typevars ?pattern?
114
115 $object info typemethods ?pattern?
116
117 $object info options ?pattern?
118
119 $object info methods ?pattern?
120
121 mymethod name ?args...?
122
123 mytypemethod name ?args...?
124
125 myproc name ?args...?
126
127 myvar name
128
129 mytypevar name
130
131 from argvName option ?defvalue?
132
133 install compName using objType objName args...
134
135 installhull using widgetType args...
136
137 installhull name
138
139 variable name
140
141 typevariable name
142
143 varname name
144
145 typevarname name
146
147 codename name
148
149 snit::boolean validate ?value?
150
151 snit::boolean name
152
153 snit::double validate ?value?
154
155 snit::double name ?option value...?
156
157 snit::enum validate ?value?
158
159 snit::enum name ?option value...?
160
161 snit::fpixels validate ?value?
162
163 snit::fpixels name ?option value...?
164
165 snit::integer validate ?value?
166
167 snit::integer name ?option value...?
168
169 snit::listtype validate ?value?
170
171 snit::listtype name ?option value...?
172
173 snit::pixels validate ?value?
174
175 snit::pixels name ?option value...?
176
177 snit::stringtype validate ?value?
178
179 snit::stringtype name ?option value...?
180
181 snit::window validate ?value?
182
183 snit::window name
184
185_________________________________________________________________
186
188 Snit is a pure Tcl object and megawidget system. It's unique among Tcl
189 object systems in that it's based not on inheritance but on delegation.
190 Object systems based on inheritance only allow you to inherit from
191 classes defined using the same system, which is limiting. In Tcl, an
192 object is anything that acts like an object; it shouldn't matter how
193 the object was implemented. Snit is intended to help you build appli‐
194 cations out of the materials at hand; thus, Snit is designed to be able
195 to incorporate and build on any object, whether it's a hand-coded
196 object, a Tk widget, an Incr Tcl object, a BWidget or almost anything
197 else.
198
199 This man page is intended to be a reference only; see the accompanying
200 snitfaq for a gentler, more tutorial introduction to Snit concepts.
201
203 This man page covers both Snit 2.1 and Snit 1.2. The primary differ‐
204 ence between the two versions is simply that Snit 2.1 contains speed
205 optimizations based on new features of Tcl 8.5; Snit 1.2 supports all
206 of Tcl 8.3, 8.4 and Tcl 8.5. There are a few minor inconsistencies;
207 they are flagged in the body of the man page with the label "Snit 1.x
208 Incompatibility"; they are also discussed in the snitfaq.
209
211 Type and Widget Definitions
212 Snit provides the following commands for defining new types:
213
214 snit::type name definition
215 Defines a new abstract data type called name. If name is not a
216 fully qualified command name, it is assumed to be a name in the
217 namespace in which the snit::type command was called (usually
218 the global namespace). It returns the fully qualified name of
219 the new type.
220
221 The type name is then a command that is used to create objects
222 of the new type, along with other activities.
223
224 The snit::type definition block is a script that may contain the
225 following definitions:
226
227 typevariable name ?-array? ?value?
228 Defines a type variable with the specified name, and
229 optionally the specified value. Type variables are
230 shared by all instances of the type. If the -array
231 option is included, then value should be a dictionary; it
232 will be assigned to the variable using array set.
233
234 typemethod name arglist body
235 Defines a type method, a subcommand of the new type com‐
236 mand, with the specified name, argument list, and body.
237 The arglist is a normal Tcl argument list and may contain
238 default arguments and the args argument; however, it may
239 not contain the argument names type, self, selfns, or
240 win.
241
242 The variable type is automatically defined in the body to
243 the type's fully-qualified name. In addition, type vari‐
244 ables are automatically visible in the body of every type
245 method.
246
247 If the name consists of two or more tokens, Snit handles
248 it specially:
249 typemethod {a b} {arg} { puts "Got $arg" }
250
251 This statement implicitly defines a type method called a
252 which has a subcommand b. b is called like this:
253 $type a b "Hello, world!"
254
255 a may have any number of subcommands. This makes it pos‐
256 sible to define a hierarchical command structure; see
257 method, below, for more examples.
258
259 Type methods can call commands from the namespace in
260 which the type is defined without importing them, e.g.,
261 if the type name is ::parentns::typename, then the type's
262 type methods can call ::parentns::someproc just as some‐
263 proc. Snit 1.x Incompatibility: This does not work in
264 Snit 1.x, as it depends on namespace path, a new command
265 in Tcl 8.5.
266
267 Snit 1.x Incompatibility: In Snit 1.x, the following fol‐
268 lowing two calls to this type method are equivalent:
269 $type a b "Hello, world!"
270 $type {a b} "Hello, world!"
271
272 In Snit 2.1, the second form is invalid.
273
274 typeconstructor body
275 The type constructor's body is executed once when the
276 type is first defined; it is typically used to initialize
277 array-valued type variables and to add entries to The Tk
278 Option Database.
279
280 The variable type is automatically defined in the body,
281 and contains the type's fully-qualified name. In addi‐
282 tion, type variables are automatically visible in the
283 body of the type constructor.
284
285 A type may define at most one type constructor.
286
287 The type constructor can call commands from the namespace
288 in which the type is defined without importing them,
289 e.g., if the type name is ::parentns::typename, then the
290 type constructor can call ::parentns::someproc just as
291 someproc. Snit 1.x Incompatibility: This does not work
292 in Snit 1.x, as it depends on namespace path, a new com‐
293 mand in Tcl 8.5.
294
295 variable name ?-array? ?value?
296 Defines an instance variable, a private variable associ‐
297 ated with each instance of this type, and optionally its
298 initial value. If the -array option is included, then
299 value should be a dictionary; it will be assigned to the
300 variable using array set.
301
302 method name arglist body
303 Defines an instance method, a subcommand of each instance
304 of this type, with the specified name, argument list and
305 body. The arglist is a normal Tcl argument list and may
306 contain default arguments and the args argument.
307
308 The method is implicitly passed the following arguments
309 as well: type, which contains the fully-qualified type
310 name; self, which contains the current instance command
311 name; selfns, which contains the name of the instance's
312 private namespace; and win, which contains the original
313 instance name. Consequently, the arglist may not contain
314 the argument names type, self, selfns, or win.
315
316 An instance method defined in this way is said to be
317 locally defined.
318
319 Type and instance variables are automatically visible in
320 all instance methods. If the type has locally defined
321 options, the options array is also visible.
322
323 If the name consists of two or more tokens, Snit handles
324 it specially:
325 method {a b} {} { ... }
326
327 This statement implicitly defines a method called a which
328 has a subcommand b. b is called like this:
329 $self a b "Hello, world!"
330
331 a may have any number of subcommands. This makes it pos‐
332 sible to define a hierarchical command structure:
333 % snit::type dog {
334 method {tail wag} {} {return "Wag, wag"}
335 method {tail droop} {} {return "Droop, droop"}
336 }
337 ::dog
338 % dog spot
339 ::spot
340 % spot tail wag
341 Wag, wag
342 % spot tail droop
343 Droop, droop
344 %
345
346 What we've done is implicitly defined a "tail" method
347 with subcommands "wag" and "droop". Consequently, it's
348 an error to define "tail" explicitly.
349
350 Methods can call commands from the namespace in which the
351 type is defined without importing them, e.g., if the type
352 name is ::parentns::typename, then the type's methods can
353 call ::parentns::someproc just as someproc. Snit 1.x
354 Incompatibility: This does not work in Snit 1.x, as it
355 depends on namespace path, a new command in Tcl 8.5.
356
357 Snit 1.x Incompatibility: In Snit 1.x, the following fol‐
358 lowing two calls to this method are equivalent:
359 $self a b "Hello, world!"
360 $self {a b} "Hello, world!"
361
362 In Snit 2.1, the second form is invalid.
363
364 option namespec ?defaultValue?
365
366 option namespec ?options...?
367 Defines an option for instances of this type, and option‐
368 ally gives it an initial value. The initial value
369 defaults to the empty string if no defaultValue is speci‐
370 fied.
371
372 An option defined in this way is said to be locally
373 defined.
374
375 The namespec is a list defining the option's name,
376 resource name, and class name, e.g.:
377 option {-font font Font} {Courier 12}
378
379 The option name must begin with a hyphen, and must not
380 contain any upper case letters. The resource name and
381 class name are optional; if not specified, the resource
382 name defaults to the option name, minus the hyphen, and
383 the class name defaults to the resource name with the
384 first letter capitalized. Thus, the following statement
385 is equivalent to the previous example:
386 option -font {Courier 12}
387
388 See The Tk Option Database for more information about
389 resource and class names.
390
391 Options are normally set and retrieved using the standard
392 instance methods configure and cget; within instance code
393 (method bodies, etc.), option values are available
394 through the options array:
395 set myfont $options(-font)
396
397 If the type defines any option handlers (e.g., -config‐
398 uremethod), then it should probably use configure and
399 cget to access its options to avoid subtle errors.
400
401 The option statement may include the following options:
402
403 -default defvalue
404 Defines the option's default value; the option's
405 default value will be "" otherwise.
406
407 -readonly flag
408 The flag can be any Boolean value recognized by
409 Tcl. If flag is true, then the option is read-
410 only--it can only be set using configure or con‐
411 figurelist at creation time, i.e., in the type's
412 constructor.
413
414 -type type
415 Every locally-defined option may define its vali‐
416 dation type, which may be either the name of a
417 validation type or a specification for a valida‐
418 tion subtype
419
420 For example, an option may declare that its value
421 must be an integer by specifying snit::integer as
422 its validation type:
423 option -number -type snit::integer
424
425 It may also declare that its value is an integer
426 between 1 and 10 by specifying a validation sub‐
427 type:
428 option -number -type {snit::integer -min 1 -max 10}
429
430 If a validation type or subtype is defined for an
431 option, then it will be used to validate the
432 option's value whenever it is changed by the
433 object's configure or configurelist methods. In
434 addition, all such options will have their values
435 validated automatically immediately after the con‐
436 structor executes.
437
438 Snit defines a family of validation types and sub‐
439 types, and it's quite simple to define new ones.
440 See Validation Types for the complete list, and
441 Defining Validation Types for an explanation of
442 how to define your own.
443
444 -cgetmethod methodName
445 Every locally-defined option may define a -cget‐
446 method; it is called when the option's value is
447 retrieved using the cget method. Whatever the
448 method's body returns will be the return value of
449 the call to cget.
450
451 The named method must take one argument, the
452 option name. For example, this code is equivalent
453 to (though slower than) Snit's default handling of
454 cget:
455 option -font -cgetmethod GetOption
456 method GetOption {option} {
457 return $options($option)
458 }
459
460 Note that it's possible for any number of options
461 to share a -cgetmethod.
462
463 -configuremethod methodName
464 Every locally-defined option may define a -config‐
465 uremethod; it is called when the option's value is
466 set using the configure or configurelist methods.
467 It is the named method's responsibility to save
468 the option's value; in other words, the value will
469 not be saved to the options() array unless the
470 method saves it there.
471
472 The named method must take two arguments, the
473 option name and its new value. For example, this
474 code is equivalent to (though slower than) Snit's
475 default handling of configure:
476 option -font -configuremethod SetOption
477 method SetOption {option value} {
478 set options($option) $value
479 }
480
481 Note that it's possible for any number of options
482 to share a single -configuremethod.
483
484 -validatemethod methodName
485 Every locally-defined option may define a -vali‐
486 datemethod; it is called when the option's value
487 is set using the configure or configurelist meth‐
488 ods, just before the -configuremethod (if any).
489 It is the named method's responsibility to vali‐
490 date the option's new value, and to throw an error
491 if the value is invalid.
492
493 The named method must take two arguments, the
494 option name and its new value. For example, this
495 code verifies that -flag's value is a valid Bool‐
496 ean value:
497 option -font -validatemethod CheckBoolean
498 method CheckBoolean {option value} {
499 if {![string is boolean -strict $value]} {
500 error "option $option must have a boolean value."
501 }
502 }
503
504 Note that it's possible for any number of options
505 to share a single -validatemethod.
506
507 constructor arglist body
508 The constructor definition specifies a body of code to be
509 executed when a new instance is created. The arglist is
510 a normal Tcl argument list and may contain default argu‐
511 ments and the args argument.
512
513 As with methods, the arguments type, self, selfns, and
514 win are defined implicitly, and all type and instance
515 variables are automatically visible in its body.
516
517 If the definition doesn't explicitly define the construc‐
518 tor, Snit defines one implicitly. If the type declares
519 at least one option (whether locally or by delegation),
520 the default constructor will be defined as follows:
521 constructor {args} {
522 $self configurelist $args
523 }
524
525 For standard Tk widget behavior, the argument list should
526 be the single name args, as shown.
527
528 If the definition defines neither a constructor nor any
529 options, the default constructor is defined as follows:
530 constructor {} {}
531
532 As with methods, the constructor can call commands from
533 the namespace in which the type is defined without
534 importing them, e.g., if the type name is ::par‐
535 entns::typename, then the constructor can call ::par‐
536 entns::someproc just as someproc. Snit 1.x Incompatibil‐
537 ity: This does not work in Snit 1.x, as it depends on
538 namespace path, a new command in Tcl 8.5.
539
540 destructor body
541 The destructor is used to code any actions that must take
542 place when an instance of the type is destroyed: typi‐
543 cally, the destruction of anything created in the con‐
544 structor.
545
546 The destructor takes no explicit arguments; as with meth‐
547 ods, the arguments type, self, selfns, and win, are
548 defined implicitly, and all type and instance variables
549 are automatically visible in its body. As with methods,
550 the destructor can call commands from the namespace in
551 which the type is defined without importing them, e.g.,
552 if the type name is ::parentns::typename, then the
553 destructor can call ::parentns::someproc just as some‐
554 proc. Snit 1.x Incompatibility: This does not work in
555 Snit 1.x, as it depends on namespace path, a new command
556 in Tcl 8.5.
557
558 proc name args body
559 Defines a new Tcl procedure in the type's namespace.
560
561 The defined proc differs from a normal Tcl proc in that
562 all type variables are automatically visible. The proc
563 can access instance variables as well, provided that it
564 is passed selfns (with precisely that name) as one of its
565 arguments.
566
567 Although they are not implicitly defined for procs, the
568 argument names type, self, and win should be avoided.
569
570 As with methods and typemethods, procs can call commands
571 from the namespace in which the type is defined without
572 importing them, e.g., if the type name is ::par‐
573 entns::typename, then the proc can call ::parentns::some‐
574 proc just as someproc. Snit 1.x Incompatibility: This
575 does not work in Snit 1.x, as it depends on namespace
576 path, a new command in Tcl 8.5.
577
578 delegate method name to comp ?as target?
579 Delegates method name to component comp. That is, when
580 method name is called on an instance of this type, the
581 method and its arguments will be passed to the named com‐
582 ponent's command instead. That is, the following state‐
583 ment
584 delegate method wag to tail
585
586 is roughly equivalent to this explicitly defined method:
587 method wag {args} {
588 uplevel $tail wag $args
589 }
590
591 As with methods, the name may have multiple tokens; in
592 this case, the last token of the name is assumed to be
593 the name of the component's method.
594
595 The optional as clause allows you to specify the dele‐
596 gated method name and possibly add some arguments:
597 delegate method wagtail to tail as "wag briskly"
598
599
600 A method cannot be both locally defined and delegated.
601
602 Note: All forms of delegate method can delegate to both
603 instance components and type components.
604
605 delegate method name ?to comp? using pattern
606 In this form of the delegate statement, the using clause
607 is used to specify the precise form of the command to
608 which method name name is delegated. In this form, the
609 to clause is optional, since the chosen command might not
610 involve any particular component.
611
612 The value of the using clause is a list that may contain
613 any or all of the following substitution codes; these
614 codes are substituted with the described value to build
615 the delegated command prefix. Note that the following
616 two statements are equivalent:
617 delegate method wag to tail
618 delegate method wag to tail using "%c %m"
619
620 Each element of the list becomes a single element of the
621 delegated command--it is never reparsed as a string.
622
623 Substitutions:
624
625 %% This is replaced with a single "%". Thus, to pass
626 the string "%c" to the command as an argument,
627 you'd write "%%c".
628
629 %c This is replaced with the named component's com‐
630 mand.
631
632 %m This is replaced with the final token of the
633 method name; if the method name has one token,
634 this is identical to %M.
635
636 %M This is replaced by the method name; if the name
637 consists of multiple tokens, they are joined by
638 space characters.
639
640 %j This is replaced by the method name; if the name
641 consists of multiple tokens, they are joined by
642 underscores ("_").
643
644 %t This is replaced with the fully qualified type
645 name.
646
647 %n This is replaced with the name of the instance's
648 private namespace.
649
650 %s This is replaced with the name of the instance
651 command.
652
653 %w This is replaced with the original name of the
654 instance command; for Snit widgets and widget
655 adaptors, it will be the Tk window name. It
656 remains constant, even if the instance command is
657 renamed.
658
659 delegate method * ?to comp? ?using pattern? ?except exceptions?
660 The form delegate method * delegates all unknown method
661 names to the specified component. The except clause can
662 be used to specify a list of exceptions, i.e., method
663 names that will not be so delegated. The using clause is
664 defined as given above. In this form, the statement must
665 contain the to clause, the using clause, or both.
666
667 In fact, the "*" can be a list of two or more tokens
668 whose last element is "*", as in the following example:
669 delegate method {tail *} to tail
670
671 This implicitly defines the method tail whose subcommands
672 will be delegated to the tail component.
673
674 delegate option namespec to comp
675
676 delegate option namespec to comp as target
677
678 delegate option * to comp
679
680 delegate option * to comp except exceptions
681 Defines a delegated option; the namespec is defined as
682 for the option statement. When the configure, config‐
683 urelist, or cget instance method is used to set or
684 retrieve the option's value, the equivalent configure or
685 cget command will be applied to the component as though
686 the option was defined with the following -config‐
687 uremethod and -cgetmethod:
688 method ConfigureMethod {option value} {
689 $comp configure $option $value
690 }
691
692 method CgetMethod {option} {
693 return [$comp cget $option]
694 }
695
696 Note that delegated options never appear in the options
697 array.
698
699 If the as clause is specified, then the target option
700 name is used in place of name.
701
702 The form delegate option * delegates all unknown options
703 to the specified component. The except clause can be
704 used to specify a list of exceptions, i.e., option names
705 that will not be so delegated.
706
707 Warning: options can only be delegated to a component if
708 it supports the configure and cget instance methods.
709
710 An option cannot be both locally defined and delegated.
711 TBD: Continue from here.
712
713 component comp ?-public method? ?-inherit flag?
714 Explicitly declares a component called comp, and automat‐
715 ically defines the component's instance variable.
716
717 If the -public option is specified, then the option is
718 made public by defining a method whose subcommands are
719 delegated to the component e.g., specifying -public
720 mycomp is equivalent to the following:
721 component mycomp
722 delegate method {mymethod *} to mycomp
723
724 If the -inherit option is specified, then flag must be a
725 Boolean value; if flag is true then all unknown methods
726 and options will be delegated to this component. The
727 name -inherit implies that instances of this new type
728 inherit, in a sense, the methods and options of the com‐
729 ponent. That is, -inherit yes is equivalent to:
730 component mycomp
731 delegate option * to mycomp
732 delegate method * to mycomp
733
734
735 delegate typemethod name to comp ?as target?
736 Delegates type method name to type component comp. That
737 is, when type method name is called on this type, the
738 type method and its arguments will be passed to the named
739 type component's command instead. That is, the following
740 statement
741 delegate typemethod lostdogs to pound
742
743 is roughly equivalent to this explicitly defined method:
744 typemethod lostdogs {args} {
745 uplevel $pound lostdogs $args
746 }
747
748 As with type methods, the name may have multiple tokens;
749 in this case, the last token of the name is assumed to be
750 the name of the component's method.
751
752 The optional as clause allows you to specify the dele‐
753 gated method name and possibly add some arguments:
754 delegate typemethod lostdogs to pound as "get lostdogs"
755
756
757 A type method cannot be both locally defined and dele‐
758 gated.
759
760 delegate typemethod name ?to comp? using pattern
761 In this form of the delegate statement, the using clause
762 is used to specify the precise form of the command to
763 which type method name name is delegated. In this form,
764 the to clause is optional, since the chosen command might
765 not involve any particular type component.
766
767 The value of the using clause is a list that may contain
768 any or all of the following substitution codes; these
769 codes are substituted with the described value to build
770 the delegated command prefix. Note that the following
771 two statements are equivalent:
772 delegate typemethod lostdogs to pound
773 delegate typemethod lostdogs to pound using "%c %m"
774
775 Each element of the list becomes a single element of the
776 delegated command--it is never reparsed as a string.
777
778 Substitutions:
779
780 %% This is replaced with a single "%". Thus, to pass
781 the string "%c" to the command as an argument,
782 you'd write "%%c".
783
784 %c This is replaced with the named type component's
785 command.
786
787 %m This is replaced with the final token of the type
788 method name; if the type method name has one
789 token, this is identical to %M.
790
791 %M This is replaced by the type method name; if the
792 name consists of multiple tokens, they are joined
793 by space characters.
794
795 %j This is replaced by the type method name; if the
796 name consists of multiple tokens, they are joined
797 by underscores ("_").
798
799 %t This is replaced with the fully qualified type
800 name.
801
802 delegate typemethod * ?to comp? ?using pattern? ?except excep‐
803 tions?
804 The form delegate typemethod * delegates all unknown type
805 method names to the specified type component. The except
806 clause can be used to specify a list of exceptions, i.e.,
807 type method names that will not be so delegated. The
808 using clause is defined as given above. In this form,
809 the statement must contain the to clause, the using
810 clause, or both.
811
812 Note: By default, Snit interprets $type foo, where foo is
813 not a defined type method, as equivalent to $type create
814 foo, where foo is the name of a new instance of the type.
815 If you use delegate typemethod *, then the create type
816 method must always be used explicitly.
817
818 The "*" can be a list of two or more tokens whose last
819 element is "*", as in the following example:
820 delegate typemethod {tail *} to tail
821
822 This implicitly defines the type method tail whose sub‐
823 commands will be delegated to the tail type component.
824
825 typecomponent comp ?-public typemethod? ?-inherit flag?
826 Explicitly declares a type component called comp, and
827 automatically defines the component's type variable. A
828 type component is an arbitrary command to which type
829 methods and instance methods can be delegated; the com‐
830 mand's name is stored in a type variable.
831
832 If the -public option is specified, then the type compo‐
833 nent is made public by defining a typemethod whose sub‐
834 commands are delegated to the type component, e.g., spec‐
835 ifying -public mytypemethod is equivalent to the follow‐
836 ing:
837 typecomponent mycomp
838 delegate typemethod {mytypemethod *} to mycomp
839
840 If the -inherit option is specified, then flag must be a
841 Boolean value; if flag is true then all unknown type
842 methods will be delegated to this type component. (See
843 the note on "delegate typemethod *", above.) The name
844 -inherit implies that this type inherits, in a sense, the
845 behavior of the type component. That is, -inherit yes is
846 equivalent to:
847 typecomponent mycomp
848 delegate typemethod * to mycomp
849
850
851 pragma ?options...?
852 The pragma statement provides control over how Snit gen‐
853 erates a type. It takes the following options; in each
854 case, flag must be a Boolean value recognized by Tcl,
855 e.g., 0, 1, yes, no, and so on.
856
857 By setting the -hastypeinfo, -hastypedestroy, and -hasin‐
858 stances pragmas to false and defining appropriate type
859 methods, you can create an ensemble command without any
860 extraneous behavior.
861
862 -canreplace flag
863 If false (the default) Snit will not create an
864 instance of a snit::type that has the same name as
865 an existing command; this prevents subtle errors.
866 Setting this pragma to true restores the behavior
867 of Snit V0.93 and earlier versions.
868
869 -hastypeinfo flag
870 If true (the default), the generated type will
871 have a type method called info that is used for
872 type introspection; the info type method is docu‐
873 mented below. If false, it will not.
874
875 -hastypedestroy flag
876 If true (the default), the generated type will
877 have a type method called destroy that is used to
878 destroy the type and all of its instances. The
879 destroy type method is documented below. If
880 false, it will not.
881
882 -hastypemethods flag
883 If true (the default), the generated type's type
884 command will have subcommands (type methods) as
885 usual. If false, the type command will serve only
886 to create instances of the type; the first argu‐
887 ment is the instance name.
888
889 This pragma and -hasinstances cannot both be set
890 false.
891
892 -hasinstances flag
893 If true (the default), the generated type will
894 have a type method called create that is used to
895 create instances of the type, along with a variety
896 of instance-related features. If false, it will
897 not.
898
899 This pragma and -hastypemethods cannot both be set
900 false.
901
902 -hasinfo flag
903 If true (the default), instances of the generated
904 type will have an instance method called info that
905 is used for instance introspection; the info
906 method is documented below. If false, it will
907 not.
908
909 -simpledispatch flag
910 This pragma is intended to make simple, heavily-
911 used abstract data types (e.g., stacks and queues)
912 more efficient.
913
914 If false (the default), instance methods are dis‐
915 patched normally. If true, a faster dispatching
916 scheme is used instead. The speed comes at a
917 price; with -simpledispatch yes you get the fol‐
918 lowing limitations:
919
920 · Methods cannot be delegated.
921
922 · uplevel and upvar do not work as expected:
923 the caller's scope is two levels up rather
924 than one.
925
926 · The option-handling methods (cget, config‐
927 ure, and configurelist) are very slightly
928 slower.
929
930 expose comp
931
932 expose comp as method
933 Deprecated. To expose component comp publicly, use com‐
934 ponent's -public option.
935
936 onconfigure name arglist body
937 Deprecated. Define option's -configuremethod option
938 instead.
939
940 As of version 0.95, the following definitions,
941 option -myoption
942 onconfigure -myoption {value} {
943 # Code to save the option's value
944 }
945
946 are implemented as follows:
947 option -myoption -configuremethod _configure-myoption
948 method _configure-myoption {_option value} {
949 # Code to save the option's value
950 }
951
952
953 oncget name body
954 Deprecated. Define option's -cgetmethod option instead.
955
956 As of version 0.95, the following definitions,
957 option -myoption
958 oncget -myoption {
959 # Code to return the option's value
960 }
961
962 are implemented as follows:
963 option -myoption -cgetmethod _cget-myoption
964 method _cget-myoption {_option} {
965 # Code to return the option's value
966 }
967
968
969 snit::widget name definition
970 This command defines a Snit megawidget type with the specified
971 name. The definition is defined as for snit::type. A
972 snit::widget differs from a snit::type in these ways:
973
974 · Every instance of a snit::widget has an automatically-
975 created component called hull, which is normally a Tk
976 frame widget. Other widgets created as part of the
977 megawidget will be created within this widget.
978
979 The hull component is initially created with the
980 requested widget name; then Snit does some magic, renam‐
981 ing the hull component and installing its own instance
982 command in its place. The hull component's new name is
983 saved in an instance variable called hull.
984
985 · The name of an instance must be valid Tk window name, and
986 the parent window must exist.
987 A snit::widget definition can include any of statements allowed in a
988 snit::type definition, and may also include the following:
989
990 widgetclass name
991 Sets the snit::widget's widget class to name, overriding
992 the default. See The Tk Option Database for more infor‐
993 mation.
994
995 hulltype type
996 Determines the kind of widget used as the snit::widget's
997 hull. The type may be frame (the default), toplevel,
998 labelframe; the qualified equivalents of these,
999 tk::frame, tk::toplevel, and tk::labelframe; or, if
1000 available, the equivalent Tile widgets: ttk::frame,
1001 ttk::toplevel, and ttk::labelframe. In practice, any
1002 widget that supports the -class option can be used as a
1003 hull widget by lappend'ing its name to the variable
1004 snit::hulltypes.
1005
1006 snit::widgetadaptor name definition
1007 This command defines a Snit megawidget type with the specified
1008 name. It differs from snit::widget in that the instance's hull
1009 component is not created automatically, but is created in the
1010 constructor and installed using the installhull command. Once
1011 the hull is installed, its instance command is renamed and
1012 replaced as with normal snit::widgets. The original command is
1013 again accessible in the instance variable hull.
1014
1015 Note that in general it is not possible to change the widget
1016 class of a snit::widgetadaptor's hull widget.
1017
1018 See The Tk Option Database for information on how snit::wid‐
1019 getadaptors interact with the option database.
1020
1021 snit::typemethod type name arglist body
1022 Defines a new type method (or redefines an existing type method)
1023 for a previously existing type.
1024
1025 snit::method type name arglist body
1026 Defines a new instance method (or redefines an existing instance
1027 method) for a previously existing type. Note that delegated
1028 instance methods can't be redefined.
1029
1030 snit::macro name arglist body
1031 Defines a Snit macro with the specified name, arglist, and body.
1032 Macros are used to define new type and widget definition state‐
1033 ments in terms of the statements defined in this man page.
1034
1035 A macro is simply a Tcl proc that is defined in the slave inter‐
1036 preter used to compile type and widget definitions. Thus,
1037 macros have access to all of the type and widget definition
1038 statements. See Macros and Meta-programming for more details.
1039
1040 The macro name cannot be the same as any standard Tcl command,
1041 or any Snit type or widget definition statement, e.g., you can't
1042 redefine the method or delegate statements, or the standard set,
1043 list, or string commands.
1044
1045 snit::compile which type body
1046 Snit defines a type, widget, or widgetadaptor by "compiling" the
1047 definition into a Tcl script; this script is then evaluated in
1048 the Tcl interpreter, which actually defines the new type.
1049
1050 This command exposes the "compiler". Given a definition body
1051 for the named type, where which is type, widget, or widgetadap‐
1052 tor, snit::compile returns a list of two elements. The first
1053 element is the fully qualified type name; the second element is
1054 the definition script.
1055
1056 snit::compile is useful when additional processing must be done
1057 on the Snit-generated code--if it must be instrumented, for
1058 example, or run through the TclDevKit compiler. In addition,
1059 the returned script could be saved in a ".tcl" file and used to
1060 define the type as part of an application or library, thus sav‐
1061 ing the compilation overhead at application start-up. Note that
1062 the same version of Snit must be used at run-time as at compile-
1063 time.
1064
1065 The Type Command
1066 A type or widget definition creates a type command, which is used to
1067 create instances of the type. The type command has this form:
1068
1069 $type typemethod args...
1070 The typemethod can be any of the Standard Type Methods (e.g.,
1071 create), or any type method defined in the type definition. The
1072 subsequent args depend on the specific typemethod chosen.
1073
1074 The type command is most often used to create new instances of
1075 the type; hence, the create method is assumed if the first argu‐
1076 ment to the type command doesn't name a valid type method,
1077 unless the type definition includes delegate typemethod * or the
1078 -hasinstances pragma is set to false.
1079
1080 Furthermore, if the -hastypemethods pragma is false, then Snit
1081 type commands can be called with no arguments at all; in this
1082 case, the type command creates an instance with an automatically
1083 generated name. In other words, provided that the -hastypemeth‐
1084 ods pragma is false and the type has instances, the following
1085 commands are equivalent:
1086 snit::type dog { ... }
1087
1088 set mydog [dog create %AUTO%]
1089 set mydog [dog %AUTO%]
1090 set mydog [dog]
1091
1092 This doesn't work for Snit widgets, for obvious reasons.
1093
1094 Snit 1.x Incompatibility: In Snit 1.x, the above behavior is
1095 available whether -hastypemethods is true (the default) or
1096 false.
1097
1098 Standard Type Methods
1099 In addition to any type methods in the type's definition, all type and
1100 widget commands will usually have at least the following subcommands:
1101
1102 $type create name ?option value ...?
1103 Creates a new instance of the type, giving it the specified name
1104 and calling the type's constructor.
1105
1106 For snit::types, if name is not a fully-qualified command name,
1107 it is assumed to be a name in the namespace in which the call to
1108 snit::type appears. The method returns the fully-qualified
1109 instance name.
1110
1111 For snit::widgets and snit::widgetadaptors, name must be a valid
1112 widget name; the method returns the widget name.
1113
1114 So long as name does not conflict with any defined type method
1115 name the create keyword may be omitted, unless the type defini‐
1116 tion includes delegate typemethod * or the -hasinstances pragma
1117 is set to false.
1118
1119 If the name includes the string %AUTO%, it will be replaced with
1120 the string $type$counter where $type is the type name and
1121 $counter is a counter that increments each time %AUTO% is used
1122 for this type.
1123
1124 By default, any arguments following the name will be a list of
1125 option names and their values; however, a type's constructor can
1126 specify a different argument list.
1127
1128 As of Snit V0.95, create will throw an error if the name is the
1129 same as any existing command--note that this was always true for
1130 snit::widgets and snit::widgetadaptors. You can restore the
1131 previous behavior using the -canreplace pragma.
1132
1133 $type info typevars ?pattern?
1134 Returns a list of the type's type variables (excluding Snit
1135 internal variables); all variable names are fully-qualified.
1136
1137 If pattern is given, it's used as a string match pattern; only
1138 names that match the pattern are returned.
1139
1140 $type info typemethods ?pattern?
1141 Returns a list of the names of the type's type methods. If the
1142 type has hierarchical type methods, whether locally-defined or
1143 delegated, only the first word of each will be included in the
1144 list.
1145
1146 If the type definition includes delegate typemethod *, the list
1147 will include only the names of those implicitly delegated type
1148 methods that have been called at least once and are still in the
1149 type method cache.
1150
1151 If pattern is given, it's used as a string match pattern; only
1152 names that match the pattern are returned.
1153
1154 $type info instances ?pattern?
1155 Returns a list of the type's instances. For snit::types, it
1156 will be a list of fully-qualified instance names; for snit::wid‐
1157 gets, it will be a list of Tk widget names.
1158
1159 If pattern is given, it's used as a string match pattern; only
1160 names that match the pattern are returned.
1161
1162 Snit 1.x Incompatibility: In Snit 1.x, the full multi-word
1163 names of hierarchical type methods are included in the return
1164 value.
1165
1166 $type destroy
1167 Destroys the type's instances, the type's namespace, and the
1168 type command itself.
1169
1170 The Instance Command
1171 A Snit type or widget's create type method creates objects of the type;
1172 each object has a unique name that is also a Tcl command. This command
1173 is used to access the object's methods and data, and has this form:
1174
1175 $object method args...
1176 The method can be any of the Standard Instance Methods, or any
1177 instance method defined in the type definition. The subsequent
1178 args depend on the specific method chosen.
1179
1180 Standard Instance Methods
1181 In addition to any delegated or locally-defined instance methods in the
1182 type's definition, all Snit objects will have at least the following
1183 subcommands:
1184
1185 $object configure ?option? ?value? ...
1186 Assigns new values to one or more options. If called with one
1187 argument, an option name, returns a list describing the option,
1188 as Tk widgets do; if called with no arguments, returns a list of
1189 lists describing all options, as Tk widgets do.
1190
1191 Warning: This information will be available for delegated
1192 options only if the component to which they are delegated has a
1193 configure method that returns this same kind of information.
1194
1195 Note: Snit defines this method only if the type has at least one
1196 option.
1197
1198 $object configurelist optionlist
1199 Like configure, but takes one argument, a list of options and
1200 their values. It's mostly useful in the type constructor, but
1201 can be used anywhere.
1202
1203 Note: Snit defines this method only if the type has at least one
1204 option.
1205
1206 $object cget option
1207 Returns the option's value.
1208
1209 Note: Snit defines this method only if the type has at least one
1210 option.
1211
1212 $object destroy
1213 Destroys the object, calling the destructor and freeing all
1214 related memory.
1215
1216 Note: The destroy method isn't defined for snit::widget or
1217 snit::widgetadaptor objects; instances of these are destroyed by
1218 calling Tk's destroy command, just as normal widgets are.
1219
1220 $object info type
1221 Returns the instance's type.
1222
1223 $object info vars ?pattern?
1224 Returns a list of the object's instance variables (excluding
1225 Snit internal variables). The names are fully qualified.
1226
1227 If pattern is given, it's used as a string match pattern; only
1228 names that match the pattern are returned.
1229
1230 $object info typevars ?pattern?
1231 Returns a list of the object's type's type variables (excluding
1232 Snit internal variables). The names are fully qualified.
1233
1234 If pattern is given, it's used as a string match pattern; only
1235 names that match the pattern are returned.
1236
1237 $object info typemethods ?pattern?
1238 Returns a list of the names of the type's type methods. If the
1239 type has hierarchical type methods, whether locally-defined or
1240 delegated, only the first word of each will be included in the
1241 list.
1242
1243 If the type definition includes delegate typemethod *, the list
1244 will include only the names of those implicitly delegated type
1245 methods that have been called at least once and are still in the
1246 type method cache.
1247
1248 If pattern is given, it's used as a string match pattern; only
1249 names that match the pattern are returned.
1250
1251 Snit 1.x Incompatibility: In Snit 1.x, the full multi-word
1252 names of hierarchical type methods are included in the return
1253 value.
1254
1255 $object info options ?pattern?
1256 Returns a list of the object's option names. This always
1257 includes local options and explicitly delegated options. If
1258 unknown options are delegated as well, and if the component to
1259 which they are delegated responds to $object configure like Tk
1260 widgets do, then the result will include all possible unknown
1261 options that can be delegated to the component.
1262
1263 If pattern is given, it's used as a string match pattern; only
1264 names that match the pattern are returned.
1265
1266 Note that the return value might be different for different
1267 instances of the same type, if component object types can vary
1268 from one instance to another.
1269
1270 $object info methods ?pattern?
1271 Returns a list of the names of the instance's methods. If the
1272 type has hierarchical methods, whether locally-defined or dele‐
1273 gated, only the first word of each will be included in the list.
1274
1275 If the type definition includes delegate method *, the list will
1276 include only the names of those implicitly delegated methods
1277 that have been called at least once and are still in the method
1278 cache.
1279
1280 If pattern is given, it's used as a string match pattern; only
1281 names that match the pattern are returned.
1282
1283 Snit 1.x Incompatibility: In Snit 1.x, the full multi-word
1284 names of hierarchical type methods are included in the return
1285 value.
1286
1287 Commands for use in Object Code
1288 Snit defines the following commands for use in your object code: that
1289 is, for use in type methods, instance methods, constructors, destruc‐
1290 tors, onconfigure handlers, oncget handlers, and procs. They do not
1291 reside in the ::snit:: namespace; instead, they are created with the
1292 type, and can be used without qualification.
1293
1294 mymethod name ?args...?
1295 The mymethod command is used for formatting callback commands to
1296 be passed to other objects. It returns a command that when
1297 called will invoke method name with the specified arguments,
1298 plus of course any arguments added by the caller. In other
1299 words, both of the following commands will cause the object's
1300 dosomething method to be called when the $button is pressed:
1301 $button configure -command [list $self dosomething myargument]
1302
1303 $button configure -command [mymethod dosomething myargument]
1304
1305 The chief distinction between the two is that the latter form
1306 will not break if the object's command is renamed.
1307
1308 mytypemethod name ?args...?
1309 The mytypemethod command is used for formatting callback com‐
1310 mands to be passed to other objects. It returns a command that
1311 when called will invoke type method name with the specified
1312 arguments, plus of course any arguments added by the caller. In
1313 other words, both of the following commands will cause the
1314 object's dosomething type method to be called when $button is
1315 pressed:
1316 $button configure -command [list $type dosomething myargument]
1317
1318 $button configure -command [mytypemethod dosomething myargument]
1319
1320 Type commands cannot be renamed, so in practice there's little
1321 difference between the two forms. mytypemethod is provided for
1322 parallelism with mymethod.
1323
1324 myproc name ?args...?
1325 The myproc command is used for formatting callback commands to
1326 be passed to other objects. It returns a command that when
1327 called will invoke the type proc name with the specified argu‐
1328 ments, plus of course any arguments added by the caller. In
1329 other words, both of the following commands will cause the
1330 object's dosomething proc to be called when $button is pressed:
1331 $button configure -command [list ${type}::dosomething myargument]
1332
1333 $button configure -command [myproc dosomething myargument]
1334
1335
1336 myvar name
1337 Given an instance variable name, returns the fully qualified
1338 name. Use this if you're passing the variable to some other
1339 object, e.g., as a -textvariable to a Tk label widget.
1340
1341 mytypevar name
1342 Given an type variable name, returns the fully qualified name.
1343 Use this if you're passing the variable to some other object,
1344 e.g., as a -textvariable to a Tk label widget.
1345
1346 from argvName option ?defvalue?
1347 The from command plucks an option value from a list of options
1348 and their values, such as is passed into a type's constructor.
1349 argvName must be the name of a variable containing such a list;
1350 option is the name of the specific option.
1351
1352 from looks for option in the option list. If it is found, it
1353 and its value are removed from the list, and the value is
1354 returned. If option doesn't appear in the list, then the def‐
1355 value is returned. If the option is locally-defined option, and
1356 defvalue is not specified, then the option's default value as
1357 specified in the type definition will be returned instead.
1358
1359 install compName using objType objName args...
1360 Creates a new object of type objType called objName and installs
1361 it as component compName, as described in Components and Delega‐
1362 tion. Any additional args... are passed along with the name to
1363 the objType command. If this is a snit::type, then the follow‐
1364 ing two commands are equivalent:
1365 install myComp using myObjType $self.myComp args...
1366
1367 set myComp [myObjType $self.myComp args...]
1368
1369 Note that whichever method is used, compName must still be
1370 declared in the type definition using component, or must be ref‐
1371 erenced in at least one delegate statement.
1372
1373 If this is a snit::widget or snit::widgetadaptor, and if options
1374 have been delegated to component compName, then those options
1375 will receive default values from the Tk option database. Note
1376 that it doesn't matter whether the component to be installed is
1377 a widget or not. See The Tk Option Database for more informa‐
1378 tion.
1379
1380 install cannot be used to install type components; just assign
1381 the type component's command name to the type component's vari‐
1382 able instead.
1383
1384 installhull using widgetType args...
1385
1386 installhull name
1387 The constructor of a snit::widgetadaptor must create a widget to
1388 be the object's hull component; the widget is installed as the
1389 hull component using this command. Note that the installed wid‐
1390 get's name must be $win. This command has two forms.
1391
1392 The first form specifies the widgetType and the args... (that
1393 is, the hardcoded option list) to use in creating the hull.
1394 Given this form, installhull creates the hull widget, and ini‐
1395 tializes any options delegated to the hull from the Tk option
1396 database.
1397
1398 In the second form, the hull widget has already been created;
1399 note that its name must be "$win". In this case, the Tk option
1400 database is not queried for any options delegated to the hull.
1401 The longer form is preferred; however, the shorter form allows
1402 the programmer to adapt a widget created elsewhere, which is
1403 sometimes useful. For example, it can be used to adapt a "page"
1404 widget created by a BWidgets tabbed notebook or pages manager
1405 widget.
1406
1407 See The Tk Option Database for more information about snit::wid‐
1408 getadaptors and the option database.
1409
1410 variable name
1411 Normally, instance variables are defined in the type definition
1412 along with the options, methods, and so forth; such instance
1413 variables are automatically visible in all instance code (e.g.,
1414 method bodies). However, instance code can use the variable
1415 command to declare instance variables that don't appear in the
1416 type definition, and also to bring variables from other names‐
1417 paces into scope in the usual way.
1418
1419 It's generally clearest to define all instance variables in the
1420 type definition, and omit declaring them in methods and so
1421 forth.
1422
1423 Note that this is an instance-specific version of the standard
1424 Tcl ::variable command.
1425
1426 typevariable name
1427 Normally, type variables are defined in the type definition,
1428 along with the instance variables; such type variables are auto‐
1429 matically visible in all of the type's code. However, type
1430 methods, instance methods and so forth can use typevariable to
1431 declare type variables that don't appear in the type definition.
1432
1433 It's generally clearest to declare all type variables in the
1434 type definition, and omit declaring them in methods, type meth‐
1435 ods, etc.
1436
1437 varname name
1438 Deprecated. Use myvar instead.
1439
1440 Given an instance variable name, returns the fully qualified
1441 name. Use this if you're passing the variable to some other
1442 object, e.g., as a -textvariable to a Tk label widget.
1443
1444 typevarname name
1445 Deprecated. Use mytypevar instead.
1446
1447 Given a type variable name, returns the fully qualified name.
1448 Use this if you're passing the type variable to some other
1449 object, e.g., as a -textvariable to a Tk label widget.
1450
1451 codename name
1452 Deprecated. Use myproc instead. Given the name of a proc (but
1453 not a type or instance method), returns the fully-qualified com‐
1454 mand name, suitable for passing as a callback.
1455
1456 Components and Delegation
1457 When an object includes other objects, as when a toolbar contains but‐
1458 tons or a GUI object contains an object that references a database, the
1459 included object is called a component. The standard way to handle com‐
1460 ponent objects owned by a Snit object is to declare them using compo‐
1461 nent, which creates a component instance variable. In the following
1462 example, a dog object has a tail object:
1463
1464 snit::type dog {
1465 component mytail
1466
1467 constructor {args} {
1468 set mytail [tail %AUTO% -partof $self]
1469 $self configurelist $args
1470 }
1471
1472 method wag {} {
1473 $mytail wag
1474 }
1475 }
1476
1477 snit::type tail {
1478 option -length 5
1479 option -partof
1480 method wag {} { return "Wag, wag, wag."}
1481 }
1482
1483
1484 Because the tail object's name is stored in an instance variable, it's
1485 easily accessible in any method.
1486
1487 The install command provides an alternate way to create and install the
1488 component:
1489
1490 snit::type dog {
1491 component mytail
1492
1493 constructor {args} {
1494 install mytail using tail %AUTO% -partof $self
1495 $self configurelist $args
1496 }
1497
1498 method wag {} {
1499 $mytail wag
1500 }
1501 }
1502
1503
1504 For snit::types, the two methods are equivalent; for snit::widgets and
1505 snit::widgetadaptors, the install command properly initializes the wid‐
1506 get's options by querying The Tk Option Database.
1507
1508 In the above examples, the dog object's wag method simply calls the
1509 tail component's wag method. In OO jargon, this is called delegation.
1510 Snit provides an easier way to do this:
1511
1512 snit::type dog {
1513 delegate method wag to mytail
1514
1515 constructor {args} {
1516 install mytail using tail %AUTO% -partof $self
1517 $self configurelist $args
1518 }
1519 }
1520
1521
1522 The delegate statement in the type definition implicitly defines the
1523 instance variable mytail to hold the component's name (though it's good
1524 form to use component to declare it explicitly); it also defines the
1525 dog object's wag method, delegating it to the mytail component.
1526
1527 If desired, all otherwise unknown methods can be delegated to a spe‐
1528 cific component:
1529
1530 snit::type dog {
1531 delegate method * to mytail
1532
1533 constructor {args} {
1534 set mytail [tail %AUTO% -partof $self]
1535 $self configurelist $args
1536 }
1537
1538 method bark { return "Bark, bark, bark!" }
1539 }
1540
1541
1542 In this case, a dog object will handle its own bark method; but wag
1543 will be passed along to mytail. Any other method, being recognized by
1544 neither dog nor tail, will simply raise an error.
1545
1546 Option delegation is similar to method delegation, except for the
1547 interactions with the Tk option database; this is described in The Tk
1548 Option Database.
1549
1550 Type Components and Delegation
1551 The relationship between type components and instance components is
1552 identical to that between type variables and instance variables, and
1553 that between type methods and instance methods. Just as an instance
1554 component is an instance variable that holds the name of a command, so
1555 a type component is a type variable that holds the name of a command.
1556 In essence, a type component is a component that's shared by every
1557 instance of the type.
1558
1559 Just as delegate method can be used to delegate methods to instance
1560 components, as described in Components and Delegation, so delegate
1561 typemethod can be used to delegate type methods to type components.
1562
1563 Note also that as of Snit 0.95 delegate method can delegate methods to
1564 both instance components and type components.
1565
1566 The Tk Option Database
1567 This section describes how Snit interacts with the Tk option database,
1568 and assumes the reader has a working knowledge of the option database
1569 and its uses. The book Practical Programming in Tcl and Tk by Welch et
1570 al has a good introduction to the option database, as does Effective
1571 Tcl/Tk Programming.
1572
1573 Snit is implemented so that most of the time it will simply do the
1574 right thing with respect to the option database, provided that the wid‐
1575 get developer does the right thing by Snit. The body of this section
1576 goes into great deal about what Snit requires. The following is a
1577 brief statement of the requirements, for reference.
1578
1579 · If the snit::widget's default widget class is not what is
1580 desired, set it explicitly using widgetclass in the widget defi‐
1581 nition.
1582
1583 · When defining or delegating options, specify the resource and
1584 class names explicitly when if the defaults aren't what you
1585 want.
1586
1587 · Use installhull using to install the hull for snit::widgetadap‐
1588 tors.
1589
1590 · Use install to install all other components.
1591
1592 The interaction of Tk widgets with the option database is a complex
1593 thing; the interaction of Snit with the option database is even more
1594 so, and repays attention to detail.
1595
1596 Setting the widget class: Every Tk widget has a widget class. For Tk
1597 widgets, the widget class name is the just the widget type name with an
1598 initial capital letter, e.g., the widget class for button widgets is
1599 "Button".
1600
1601 Similarly, the widget class of a snit::widget defaults to the unquali‐
1602 fied type name with the first letter capitalized. For example, the
1603 widget class of
1604
1605 snit::widget ::mylibrary::scrolledText { ... }
1606
1607 is "ScrolledText". The widget class can also be set explicitly using
1608 the widgetclass statement within the snit::widget definition.
1609
1610 Any widget can be used as the hulltype provided that it supports the
1611 -class option for changing its widget class name. See the discussion
1612 of the hulltype command, above.
1613
1614 The widget class of a snit::widgetadaptor is just the widget class of
1615 its hull widget; this cannot be changed unless the hull widget supports
1616 -class, in which case it will usually make more sense to use snit::wid‐
1617 get rather than snit::widgetadaptor.
1618
1619 Setting option resource names and classes: In Tk, every option has
1620 three names: the option name, the resource name, and the class name.
1621 The option name begins with a hyphen and is all lowercase; it's used
1622 when creating widgets, and with the configure and cget commands.
1623
1624 The resource and class names are used to initialize option default val‐
1625 ues by querying the Tk option database. The resource name is usually
1626 just the option name minus the hyphen, but may contain uppercase let‐
1627 ters at word boundaries; the class name is usually just the resource
1628 name with an initial capital, but not always. For example, here are
1629 the option, resource, and class names for several text widget options:
1630
1631 -background background Background
1632 -borderwidth borderWidth BorderWidth
1633 -insertborderwidth insertBorderWidth BorderWidth
1634 -padx padX Pad
1635
1636
1637 As is easily seen, sometimes the resource and class names can be
1638 inferred from the option name, but not always.
1639
1640 Snit options also have a resource name and a class name. By default,
1641 these names follow the rule given above: the resource name is the
1642 option name without the hyphen, and the class name is the resource name
1643 with an initial capital. This is true for both locally-defined options
1644 and explicitly delegated options:
1645
1646 snit::widget mywidget {
1647 option -background
1648 delegate option -borderwidth to hull
1649 delegate option * to text
1650 # ...
1651 }
1652
1653
1654 In this case, the widget class name is "Mywidget". The widget has the
1655 following options: -background, which is locally defined, and -border‐
1656 width, which is explicitly delegated; all other widgets are delegated
1657 to a component called "text", which is probably a Tk text widget. If
1658 so, mywidget has all the same options as a text widget. The option,
1659 resource, and class names are as follows:
1660
1661 -background background Background
1662 -borderwidth borderwidth Borderwidth
1663 -padx padX Pad
1664
1665
1666 Note that the locally defined option, -background, happens to have the
1667 same three names as the standard Tk -background option; and -pad, which
1668 is delegated implicitly to the text component, has the same three names
1669 for mywidget as it does for the text widget. -borderwidth, on the
1670 other hand, has different resource and class names than usual, because
1671 the internal word "width" isn't capitalized. For consistency, it
1672 should be; this is done as follows:
1673
1674 snit::widget mywidget {
1675 option -background
1676 delegate option {-borderwidth borderWidth} to hull
1677 delegate option * to text
1678 # ...
1679 }
1680
1681
1682 The class name will default to "BorderWidth", as expected.
1683
1684 Suppose, however, that mywidget also delegated -padx and -pady to the
1685 hull. In this case, both the resource name and the class name must be
1686 specified explicitly:
1687
1688 snit::widget mywidget {
1689 option -background
1690 delegate option {-borderwidth borderWidth} to hull
1691 delegate option {-padx padX Pad} to hull
1692 delegate option {-pady padY Pad} to hull
1693 delegate option * to text
1694 # ...
1695 }
1696
1697
1698 Querying the option database: If you set your widgetclass and option
1699 names as described above, Snit will query the option database when each
1700 instance is created, and will generally do the right thing when it
1701 comes to querying the option database. The remainder of this section
1702 goes into the gory details.
1703
1704 Initializing locally defined options: When an instance of a snit::wid‐
1705 get is created, its locally defined options are initialized as follows:
1706 each option's resource and class names are used to query the Tk option
1707 database. If the result is non-empty, it is used as the option's
1708 default; otherwise, the default hardcoded in the type definition is
1709 used. In either case, the default can be overridden by the caller.
1710 For example,
1711
1712 option add *Mywidget.texture pebbled
1713
1714 snit::widget mywidget {
1715 option -texture smooth
1716 # ...
1717 }
1718
1719 mywidget .mywidget -texture greasy
1720
1721
1722 Here, -texture would normally default to "smooth", but because of the
1723 entry added to the option database it defaults to "pebbled". However,
1724 the caller has explicitly overridden the default, and so the new widget
1725 will be "greasy".
1726
1727 Initializing options delegated to the hull: A snit::widget's hull is a
1728 widget, and given that its class has been set it is expected to query
1729 the option database for itself. The only exception concerns options
1730 that are delegated to it with a different name. Consider the following
1731 code:
1732
1733 option add *Mywidget.borderWidth 5
1734 option add *Mywidget.relief sunken
1735 option add *Mywidget.hullbackground red
1736 option add *Mywidget.background green
1737
1738 snit::widget mywidget {
1739 delegate option -borderwidth to hull
1740 delegate option -hullbackground to hull as -background
1741 delegate option * to hull
1742 # ...
1743 }
1744
1745 mywidget .mywidget
1746
1747 set A [.mywidget cget -relief]
1748 set B [.mywidget cget -hullbackground]
1749 set C [.mywidget cget -background]
1750 set D [.mywidget cget -borderwidth]
1751
1752
1753 The question is, what are the values of variables A, B, C and D?
1754
1755 The value of A is "sunken". The hull is a Tk frame that has been given
1756 the widget class "Mywidget"; it will automatically query the option
1757 database and pick up this value. Since the -relief option is implic‐
1758 itly delegated to the hull, Snit takes no action.
1759
1760 The value of B is "red". The hull will automatically pick up the value
1761 "green" for its -background option, just as it picked up the -relief
1762 value. However, Snit knows that -hullbackground is mapped to the
1763 hull's -background option; hence, it queries the option database for
1764 -hullbackground and gets "red" and updates the hull accordingly.
1765
1766 The value of C is also "red", because -background is implicitly dele‐
1767 gated to the hull; thus, retrieving it is the same as retrieving -hull‐
1768 background. Note that this case is unusual; in practice, -background
1769 would probably be explicitly delegated to some other component.
1770
1771 The value of D is "5", but not for the reason you think. Note that as
1772 it is defined above, the resource name for -borderwidth defaults to
1773 "borderwidth", whereas the option database entry is "borderWidth". As
1774 with -relief, the hull picks up its own -borderwidth option before Snit
1775 does anything. Because the option is delegated under its own name,
1776 Snit assumes that the correct thing has happened, and doesn't worry
1777 about it any further.
1778
1779 For snit::widgetadaptors, the case is somewhat altered. Widget adap‐
1780 tors retain the widget class of their hull, and the hull is not created
1781 automatically by Snit. Instead, the snit::widgetadaptor must call
1782 installhull in its constructor. The normal way to do this is as fol‐
1783 lows:
1784
1785 snit::widgetadaptor mywidget {
1786 # ...
1787 constructor {args} {
1788 # ...
1789 installhull using text -foreground white
1790 #
1791 }
1792 #...
1793 }
1794
1795
1796 In this case, the installhull command will create the hull using a com‐
1797 mand like this:
1798
1799 set hull [text $win -foreground white]
1800
1801
1802 The hull is a text widget, so its widget class is "Text". Just as with
1803 snit::widget hulls, Snit assumes that it will pick up all of its normal
1804 option values automatically; options delegated from a different name
1805 are initialized from the option database in the same way.
1806
1807 Initializing options delegated to other components: Non-hull components
1808 are matched against the option database in two ways. First, a compo‐
1809 nent widget remains a widget still, and therefore is initialized from
1810 the option database in the usual way. Second, the option database is
1811 queried for all options delegated to the component, and the component
1812 is initialized accordingly--provided that the install command is used
1813 to create it.
1814
1815 Before option database support was added to Snit, the usual way to cre‐
1816 ate a component was to simply create it in the constructor and assign
1817 its command name to the component variable:
1818
1819 snit::widget mywidget {
1820 delegate option -background to myComp
1821
1822 constructor {args} {
1823 set myComp [text $win.text -foreground black]
1824 }
1825 }
1826
1827
1828 The drawback of this method is that Snit has no opportunity to initial‐
1829 ize the component properly. Hence, the following approach is now used:
1830
1831 snit::widget mywidget {
1832 delegate option -background to myComp
1833
1834 constructor {args} {
1835 install myComp using text $win.text -foreground black
1836 }
1837 }
1838
1839
1840 The install command does the following:
1841
1842 · Builds a list of the options explicitly included in the install
1843 command -- in this case, -foreground.
1844
1845 · Queries the option database for all options delegated explicitly
1846 to the named component.
1847
1848 · Creates the component using the specified command, after insert‐
1849 ing into it a list of options and values read from the option
1850 database. Thus, the explicitly included options (-foreground)
1851 will override anything read from the option database.
1852
1853 · If the widget definition implicitly delegated options to the
1854 component using delegate option *, then Snit calls the newly
1855 created component's configure method to receive a list of all of
1856 the component's options. From this Snit builds a list of
1857 options implicitly delegated to the component that were not
1858 explicitly included in the install command. For all such
1859 options, Snit queries the option database and configures the
1860 component accordingly.
1861
1862 Non-widget components: The option database is never queried for
1863 snit::types, since it can only be queried given a Tk widget name. How‐
1864 ever, snit::widgets can have non-widget components. And if options are
1865 delegated to those components, and if the install command is used to
1866 install those components, then they will be initialized from the option
1867 database just as widget components are.
1868
1869 Macros and Meta-programming
1870 The snit::macro command enables a certain amount of meta-programming
1871 with Snit classes. For example, suppose you like to define properties:
1872 instance variables that have set/get methods. Your code might look
1873 like this:
1874 snit::type dog {
1875 variable mood happy
1876
1877 method getmood {} {
1878 return $mood
1879 }
1880
1881 method setmood {newmood} {
1882 set mood $newmood
1883 }
1884 }
1885
1886 That's nine lines of text per property. Or, you could define the fol‐
1887 lowing snit::macro:
1888 snit::macro property {name initValue} {
1889 variable $name $initValue
1890
1891 method get$name {} "return $name"
1892
1893 method set$name {value} "set $name \$value"
1894 }
1895
1896 Note that a snit::macro is just a normal Tcl proc defined in the slave
1897 interpreter used to compile type and widget definitions; as a result,
1898 it has access to all the commands used to define types and widgets.
1899
1900 Given this new macro, you can define a property in one line of code:
1901 snit::type dog {
1902 property mood happy
1903 }
1904
1905 Within a macro, the commands variable and proc refer to the Snit type-
1906 definition commands, not the standard Tcl commands. To get the stan‐
1907 dard Tcl commands, use _variable and _proc.
1908
1909 Because a single slave interpreter is used for compiling all Snit types
1910 and widgets in the application, there's the possibility of macro name
1911 collisions. If you're writing a reuseable package using Snit, and you
1912 use some snit::macros, define them in your package namespace:
1913 snit::macro mypkg::property {name initValue} { ... }
1914
1915 snit::type dog {
1916 mypkg::property mood happy
1917 }
1918
1919 This leaves the global namespace open for application authors.
1920
1921 Validation Types
1922 A validation type is an object that can be used to validate Tcl values
1923 of a particular kind. For example, snit::integer is used to validate
1924 that a Tcl value is an integer.
1925
1926 Every validation type has a validate method which is used to do the
1927 validation. This method must take a single argument, the value to be
1928 validated; further, it must do nothing if the value is valid, but throw
1929 an error if the value is invalid:
1930 snit::integer validate 5 ;# Does nothing
1931 snit::integer validate 5.0 ;# Throws an error (not an integer!)
1932
1933
1934 Snit defines a family of validation types, all of which are implemented
1935 as snit::type's. They can be used as is; in addition, their instances
1936 serve as parameterized subtypes. For example, a probability is a num‐
1937 ber between 0.0 and 1.0 inclusive:
1938 snit::double probability -min 0.0 -max 1.0
1939
1940 The example above creates an instance of snit::double--a validation
1941 subtype--called probability, which can be used to validate probability
1942 values:
1943 probability validate 0.5 ;# Does nothing
1944 probability validate 7.9 ;# Throws an error
1945
1946 Validation subtypes can be defined explicitly, as in the above example;
1947 when a locally-defined option's -type is specified, they may also be
1948 created on the fly:
1949 snit::enum ::dog::breed -values {mutt retriever sheepdog}
1950
1951 snit::type dog {
1952 # Define subtypes on the fly...
1953 option -breed -type {
1954 snit::enum -values {mutt retriever sheepdog}
1955 }
1956
1957 # Or use predefined subtypes...
1958 option -breed -type ::dog::breed
1959 }
1960
1961
1962 Any object that has a validate method with the semantics described
1963 above can be used as a validation type; see Defining Validation Types
1964 for information on how to define new ones.
1965
1966 Snit defines the following validation types:
1967
1968 snit::boolean validate ?value?
1969
1970 snit::boolean name
1971 Validates Tcl boolean values: 1, 0, on, off, yes, no, true,
1972 false. It's possible to define subtypes--that is, instances--of
1973 snit::boolean, but as it has no options there's no reason to do
1974 so.
1975
1976 snit::double validate ?value?
1977
1978 snit::double name ?option value...?
1979 Validates floating-point values. Subtypes may be created with
1980 the following options:
1981
1982 -min min
1983 Specifies a floating-point minimum bound; a value is
1984 invalid if it is strictly less than min.
1985
1986 -max max
1987 Specifies a floating-point maximum bound; a value is
1988 invalid if it is strictly greater than max.
1989
1990 snit::enum validate ?value?
1991
1992 snit::enum name ?option value...?
1993 Validates that a value comes from an enumerated list. The base
1994 type is of little use by itself, as only subtypes actually have
1995 an enumerated list to validate against. Subtypes may be created
1996 with the following options:
1997
1998 -values list
1999 Specifies a list of valid values. A value is valid if
2000 and only if it's included in the list.
2001
2002 snit::fpixels validate ?value?
2003
2004 snit::fpixels name ?option value...?
2005 Tk programs only. Validates screen distances, in any of the
2006 forms accepted by winfo fpixels. Subtypes may be created with
2007 the following options:
2008
2009 -min min
2010 Specifies a minimum bound; a value is invalid if it is
2011 strictly less than min. The bound may be expressed in
2012 any of the forms accepted by winfo fpixels.
2013
2014 -max max
2015 Specifies a maximum bound; a value is invalid if it is
2016 strictly greater than max. The bound may be expressed in
2017 any of the forms accepted by winfo fpixels.
2018
2019 snit::integer validate ?value?
2020
2021 snit::integer name ?option value...?
2022 Validates integer values. Subtypes may be created with the fol‐
2023 lowing options:
2024
2025 -min min
2026 Specifies an integer minimum bound; a value is invalid if
2027 it is strictly less than min.
2028
2029 -max max
2030 Specifies an integer maximum bound; a value is invalid if
2031 it is strictly greater than max.
2032
2033 snit::listtype validate ?value?
2034
2035 snit::listtype name ?option value...?
2036 Validates Tcl lists. Subtypes may be created with the following
2037 options:
2038
2039 -minlen min
2040 Specifies a minimum list length; the value is invalid if
2041 it has fewer than min elements. Defaults to 0.
2042
2043 -maxlen max
2044 Specifies a maximum list length; the value is invalid if
2045 it more than max elements.
2046
2047 -type type
2048 Specifies the type of the list elements; type must be the
2049 name of a validation type or subtype. In the following
2050 example, the value of -numbers must be a list of inte‐
2051 gers.
2052 option -numbers -type {snit::listtype -type snit::integer}
2053
2054 Note that this option doesn't support defining new vali‐
2055 dation subtypes on the fly; that is, the following code
2056 will not work (yet, anyway):
2057 option -numbers -type {
2058 snit::listtype -type {snit::integer -min 5}
2059 }
2060
2061 Instead, define the subtype explicitly:
2062 snit::integer gt4 -min 5
2063
2064 snit::type mytype {
2065 option -numbers -type {snit::listtype -type gt4}
2066 }
2067
2068
2069 snit::pixels validate ?value?
2070
2071 snit::pixels name ?option value...?
2072 Tk programs only. Validates screen distances, in any of the
2073 forms accepted by winfo pixels. Subtypes may be created with the
2074 following options:
2075
2076 -min min
2077 Specifies a minimum bound; a value is invalid if it is
2078 strictly less than min. The bound may be expressed in
2079 any of the forms accepted by winfo pixels.
2080
2081 -max max
2082 Specifies a maximum bound; a value is invalid if it is
2083 strictly greater than max. The bound may be expressed in
2084 any of the forms accepted by winfo pixels.
2085
2086 snit::stringtype validate ?value?
2087
2088 snit::stringtype name ?option value...?
2089 Validates Tcl strings. The base type is of little use by itself,
2090 since very Tcl value is also a valid string. Subtypes may be
2091 created with the following options:
2092
2093 -minlen min
2094 Specifies a minimum string length; the value is invalid
2095 if it has fewer than min characters. Defaults to 0.
2096
2097 -maxlen max
2098 Specifies a maximum string length; the value is invalid
2099 if it has more than max characters.
2100
2101 -glob pattern
2102 Specifies a string match pattern; the value is invalid if
2103 it doesn't match the pattern.
2104
2105 -regexp regexp
2106 Specifies a regular expression; the value is invalid if
2107 it doesn't match the regular expression.
2108
2109 -nocase flag
2110 By default, both -glob and -regexp matches are case-sen‐
2111 sitive. If -nocase is set to true, then both -glob and
2112 -regexp matches are case-insensitive.
2113
2114 snit::window validate ?value?
2115
2116 snit::window name
2117 Tk programs only. Validates Tk window names. The value must
2118 cause winfo exists to return true; otherwise, the value is
2119 invalid. It's possible to define subtypes--that is,
2120 instances--of snit::window, but as it has no options at present
2121 there's no reason to do so.
2122
2123 Defining Validation Types
2124 There are three ways to define a new validation type: as a subtype of
2125 one of Snit's validation types, as a validation type command, and as a
2126 full-fledged validation type similar to those provided by Snit. Defin‐
2127 ing subtypes of Snit's validation types is described above, under Vali‐
2128 dation Types.
2129
2130 The next simplest way to create a new validation type is as a valida‐
2131 tion type command. A validation type is simply an object that has a
2132 validate method; the validate method must take one argument, a value,
2133 and throw an error if the value is invalid. This can be done with a
2134 simple proc. For example, the snit::boolean validate type could have
2135 been implemented like this:
2136 proc ::snit::boolean {"validate" value} {
2137 if {![string is boolean -strict $value]} {
2138 return -code error "invalid boolean \"$value\", should be one of: 1, 0, ..."
2139 }
2140
2141 return
2142 }
2143
2144 A validation type defined in this way cannot be subtyped, of course;
2145 but for many applications this will be sufficient.
2146
2147 Finally, one can define a full-fledged, subtype-able validation type as
2148 a snit::type. Here's a skeleton to get you started:
2149 snit::type myinteger {
2150 # First, define any options you'd like to use to define
2151 # subtypes. Give them defaults such that they won't take
2152 # effect if they aren't used, and marked them "read-only".
2153 # After all, you shouldn't be changing their values after
2154 # a subtype is defined.
2155 #
2156 # For example:
2157
2158 option -min -default "" -readonly 1
2159 option -max -default "" -readonly 1
2160
2161 # Next, define a "validate" type method which should do the
2162 # validation in the basic case. This will allow the
2163 # type command to be used as a validation type.
2164
2165 typemethod validate {value} {
2166 if {![string is integer -strict $value]} {
2167 return -code error "invalid value \"$value\", expected integer"
2168 }
2169
2170 return
2171 }
2172
2173 # Next, the constructor should validate the subtype options,
2174 # if any. Since they are all readonly, we don't need to worry
2175 # about validating the options on change.
2176
2177 constructor {args} {
2178 # FIRST, get the options
2179 $self configurelist $args
2180
2181 # NEXT, validate them.
2182
2183 # I'll leave this to your imagination.
2184 }
2185
2186 # Next, define a "validate" instance method; its job is to
2187 # validate values for subtypes.
2188
2189 method validate {value} {
2190 # First, call the type method to do the basic validation.
2191 $type validate $value
2192
2193 # Now we know it's a valid integer.
2194
2195 if {("" != $options(-min) && $value < $options(-min)) ||
2196 ("" != $options(-max) && $value > $options(-max))} {
2197 # It's out of range; format a detailed message about
2198 # the error, and throw it.
2199
2200 set msg "...."
2201
2202 return -code error $msg
2203 }
2204
2205 # Otherwise, if it's valid just return.
2206 return
2207 }
2208 }
2209
2210 And now you have a type that can be subtyped.
2211
2212 The file "validate.tcl" in the Snit distribution defines all of Snit's
2213 validation types; you can find the complete implementation for
2214 snit::integer and the other types there, to use as examples for your
2215 own types.
2216
2218 If you have problems, find bugs, or new ideas you are hereby cordially
2219 invited to submit a report of your problem, bug, or idea at the Source‐
2220 Forge trackers for tcllib, which can be found at http://source‐
2221 forge.net/projects/tcllib/. The relevant category is snit.
2222
2223 Additionally, you might wish to join the Snit mailing list; see
2224 http://www.wjduquette.com/snit for details.
2225
2226 One particular area to watch is using snit::widgetadaptor to adapt
2227 megawidgets created by other megawidget packages; correct widget
2228 destruction depends on the order of the <Destroy> bindings. The wisest
2229 course is simply not to do this.
2230
2232 · Error stack traces returned by Snit 1.x are extremely ugly and
2233 typically contain far too much information about Snit internals.
2234 The error messages are much improved in Snit 2.1.
2235
2236 · Also see the SourceForge Trackers at http://source‐
2237 forge.net/projects/tcllib/, category snit.
2238
2240 During the course of developing Notebook (See http://www.wjdu‐
2241 quette.com/notebook), my Tcl-based personal notebook application, I
2242 found I was writing it as a collection of objects. I wasn't using any
2243 particular object-oriented framework; I was just writing objects in
2244 pure Tcl following the guidelines in my Guide to Object Commands (see
2245 http://www.wjduquette.com/tcl/objects.html), along with a few other
2246 tricks I'd picked up since. And though it was working well, it quickly
2247 became tiresome because of the amount of boilerplate code associated
2248 with each new object type.
2249
2250 So that was one thing--tedium is a powerful motivator. But the other
2251 thing I noticed is that I wasn't using inheritance at all, and I wasn't
2252 missing it. Instead, I was using delegation: objects that created
2253 other objects and delegated methods to them.
2254
2255 And I said to myself, "This is getting tedious...there has got to be a
2256 better way." And one afternoon, on a whim, I started working on Snit,
2257 an object system that works the way Tcl works. Snit doesn't support
2258 inheritance, but it's great at delegation, and it makes creating megaw‐
2259 idgets easy.
2260
2261 If you have any comments or suggestions (or bug reports!) don't hesi‐
2262 tate to send me e-mail at will@wjduquette.com. In addition, there's a
2263 Snit mailing list; you can find out more about it at the Snit home page
2264 (see http://www.wjduquette.com/snit).
2265
2267 Snit has been designed and implemented from the very beginning by
2268 William H. Duquette. However, much credit belongs to the following
2269 people for using Snit and providing me with valuable feedback: Rolf
2270 Ade, Colin McCormack, Jose Nazario, Jeff Godfrey, Maurice Diamanti,
2271 Egon Pasztor, David S. Cargo, Tom Krehbiel, Michael Cleverly, Andreas
2272 Kupries, Marty Backe, Andy Goth, Jeff Hobbs, Brian Griffin, Donal Fel‐
2273 lows, Miguel Sofer, Kenneth Green, and Anton Kovalenko. If I've for‐
2274 gotten anyone, my apologies; let me know and I'll add your name to the
2275 list.
2276
2278 BWidget, C++, Incr Tcl, Snit, adaptors, class, mega widget, object,
2279 object oriented, type, widget, widget adaptors
2280
2282 Copyright (c) 2003-2006, by William H. Duquette
2283
2284
2285
2286
2287snit 2.1 snit(n)