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