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