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