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