commit a copy of snit
[scpubgit/TenDotTcl.git] / snit / snitfaq.man
1 [comment {-*- tcl -*- doctools manpage}]
2 [manpage_begin snitfaq n 2.2]
3 [copyright {2003-2006, by William H. Duquette}]
4 [moddesc {Snit's Not Incr Tcl, OO system}]
5 [titledesc   {Snit Frequently Asked Questions}]
6 [category  {Programming tools}]
7 [description]
8 [para]
9
10 [section OVERVIEW]
11
12 [subsection {What is this document?}]
13
14 This is an atypical FAQ list, in that few of the questions are
15 frequently asked.  Rather, these are the questions I think a newcomer
16 to Snit should be asking.  This file is not a complete reference to
17 Snit, however; that information is in the [cmd snit] man page.
18
19 [subsection {What is Snit?}]
20
21 Snit is a framework for defining abstract data types and megawidgets
22 in pure Tcl.  The name "Snit" stands for "Snit's Not Incr Tcl", 
23 signifying that Snit takes a different approach to defining objects 
24 than does Incr Tcl, the best known object framework for Tcl.  Had
25 I realized that Snit would become at all popular, I'd probably have
26 chosen something else.
27
28 [para]
29
30 The primary purpose of Snit is to be [term "object glue"]--to help you
31 compose diverse objects from diverse sources into types and
32 megawidgets with clean, convenient interfaces so that you can more
33 easily build your application.
34
35 [para]
36
37 Snit isn't about theoretical purity or minimalist design; it's about
38 being able to do powerful things easily and consistently without
39 having to think about them--so that you can concentrate on building
40 your application. 
41
42 [para]
43
44 Snit isn't about implementing thousands of nearly identical
45 carefully-specified lightweight thingamajigs--not as individual Snit
46 objects.  Traditional Tcl methods will be much faster, and not much
47 more complicated.  But Snit [emph is] about implementing a clean interface
48 to manage a collection of thousands of nearly identical
49 carefully-specified lightweight thingamajigs (e.g., think of the text
50 widget and text tags, or the canvas widget and canvas objects).  Snit
51 lets you hide the details of just how those thingamajigs are
52 stored--so that you can ignore it, and concentrate on building your
53 application. 
54
55 [para]
56
57 Snit isn't a way of life, a silver bullet, or the Fountain of
58 Youth. It's just a way of managing complexity--and of managing some of
59 the complexity of managing complexity--so that you can concentrate on
60 building your application. 
61
62 [subsection {What version of Tcl does Snit require?}]
63
64 Snit 1.3 requires Tcl 8.3 or later; Snit 2.2 requires Tcl 8.5 or
65 later.  See [sectref {SNIT VERSIONS}] for the differences between Snit
66 1.3 and Snit 2.2.
67
68 [subsection {Where can I download Snit?}]
69
70 Snit is part of Tcllib, the standard Tcl library, so you might already
71 have it.  It's also available at the Snit Home Page,
72 [uri http://www.wjduquette.com/snit].
73
74 [subsection {What are Snit's goals?}]
75
76 [para]
77
78 [list_begin itemized]
79 [item]
80
81 A Snit object should be at least as efficient as a hand-coded Tcl
82 object (see [uri http://www.wjduquette.com/tcl/objects.html]).
83
84 [item]
85
86 The fact that Snit was used in an object's implementation should be
87 transparent (and irrelevant) to clients of that object.
88
89 [item]
90
91 Snit should be able to encapsulate objects from other sources,
92 particularly Tk widgets.
93
94 [item]
95
96 Snit megawidgets should be (to the extent possible) indistinguishable
97 in interface from Tk widgets.
98
99 [item]
100
101 Snit should be Tclish--that is, rather than trying to emulate C++,
102 Smalltalk, or anything else, it should try to emulate Tcl itself.
103
104 [item]
105
106 It should have a simple, easy-to-use, easy-to-remember syntax.
107
108 [list_end]
109
110 [subsection {How is Snit different from other OO frameworks?}]
111
112 Snit is unique among Tcl object systems in that
113 it is based not on inheritance but on delegation.  Object
114 systems based on inheritance only allow you to inherit from classes
115 defined using the same system, and that's a shame.  In Tcl, an object
116 is anything that acts like an object; it shouldn't matter how the
117 object was implemented.  I designed Snit to help me build applications
118 out of the materials at hand; thus, Snit is designed to be able to
119 incorporate and build on any object, whether it's a hand-coded object,
120 a Tk widget, an Incr Tcl object, a BWidget or almost anything else.
121
122 [para]
123
124 Note that you can achieve the effect of inheritance using 
125 [sectref COMPONENTS] and [sectref "DELEGATION"]--and you can inherit
126 from anything that looks like a Tcl object.
127
128 [subsection {What can I do with Snit?}]
129
130 Using Snit, a programmer can:
131
132 [list_begin itemized]
133 [item]
134
135 Create abstract data types and Tk megawidgets.
136
137 [item]
138
139 Define instance variables, type variables, and Tk-style options.
140
141 [item]
142
143 Define constructors, destructors, instance methods, type methods, procs.
144
145 [item]
146
147 Assemble a type out of component types.  Instance methods and options
148 can be delegated to the component types automatically.
149
150 [list_end]
151
152 [section {SNIT VERSIONS}]
153
154 [subsection {Which version of Snit should I use?}]
155
156 The current Snit distribution includes two versions, Snit 1.3 and Snit
157 2.2.  The reason that both are included is that Snit 2.2 takes
158 advantage of a number of new features of Tcl 8.5 to improve run-time
159 efficiency; as a side-effect, the ugliness of Snit's error messages
160 and stack traces has been reduced considerably.  The cost of using
161 Snit 2.2, of course, is that you must target Tcl 8.5.
162
163 [para]
164
165 Snit 1.3, on the other hand, lacks Snit 2.2's optimizations, but
166 requires only Tcl 8.3 and later.
167
168 [para]
169
170 In short, if you're targetting Tcl 8.3 or 8.4 you should use Snit 1.3.  If
171 you can afford to target Tcl 8.5, you should definitely use Snit 2.2.
172 If you will be targetting both, you can use Snit 1.3 exclusively, or
173 (if your code is unaffected by the minor incompatibilities between the
174 two versions) you can use Snit 1.3 for Tcl 8.4 and Snit 2.2 for Tcl
175 8.5.
176
177 [subsection {How do I select the version of Snit I want to use?}]
178
179 To always use Snit 1.3 (or a later version of Snit 1.x), invoke Snit
180 as follows:
181
182 [example {package require snit 1.3
183 }]
184
185 To always use Snit 2.2 (or a later version of Snit 2.x), say this
186 instead:
187
188 [example {package require snit 2.2
189 }]
190
191 Note that if you request Snit 2.2 explicitly, your application will
192 halt with Tcl 8.4, since Snit 2.2 is unavailable for Tcl 8.4.
193
194 [para]
195
196 If you wish your application to always use the latest available
197 version of Snit, don't specify a version number:
198
199 [example {package require snit
200 }]
201
202 Tcl will find and load the latest version that's available relative to
203 the version of Tcl being used.  In this case, be careful to avoid
204 using any incompatible features.
205
206 [subsection {How are Snit 1.3 and Snit 2.2 incompatible?}]
207
208 To the extent possible, Snit 2.2 is intended to be a drop-in
209 replacement for Snit 1.3. Unfortunately, some incompatibilities were
210 inevitable because Snit 2.2 uses Tcl 8.5's new 
211 [cmd "namespace ensemble"] mechanism to implement subcommand dispatch.
212 This approach is much faster than the mechanism used in Snit 1.3, and
213 also results in much better error messages; however, it also places
214 new constraints on the implementation.
215
216 [para]
217
218 There are four specific incompatibilities between Snit 1.3 and Snit 2.2.
219
220 [para]
221
222 [list_begin itemized]
223 [item]
224
225 Snit 1.3 supports implicit naming of objects.  Suppose you define a
226 new [cmd snit::type] called [cmd dog].  You can create instances of
227 [cmd dog] in three ways:
228
229 [example {dog spot               ;# Explicit naming
230 set obj1 [dog %AUTO%]  ;# Automatic naming
231 set obj2 [dog]         ;# Implicit naming
232 }]
233
234 In Snit 2.2, type commands are defined using the [cmd "namespace ensemble"]
235 mechanism; and [cmd "namespace ensemble"] doesn't allow an ensemble command
236 to be called without a subcommand.  In short, using 
237 [cmd "namespace ensemble"] there's no way to support implicit naming.
238
239 [para]
240
241 All is not lost, however.  If the type has no type methods, then the
242 type command is a simple command rather than an ensemble, and 
243 [cmd "namespace ensemble"] is not used.  In this case, implicit naming
244 is still possible.
245
246 [para]
247
248 In short, you can have implicit naming if you're willing to do without
249 type methods (including the standard type methods, like 
250 [cmd "\$type info"]).  To do so, use the [const -hastypemethods] pragma:
251
252 [example {pragma -hastypemethods 0}]
253
254 [item]
255 Hierarchical methods and type methods are implemented differently in
256 Snit 2.2.  
257
258 [para]
259
260 A hierarchical method is an instance method which has
261 subcommands; these subcommands are themselves methods.  The Tk text
262 widget's [cmd tag] command and its subcommands are examples of 
263 hierarchical methods.  You can implement such subcommands in Snit
264 simply by including multiple words in the method names:
265
266 [example {method {tag configure} {tag args} { ... }
267
268 method {tag cget} {tag option} {...}
269 }]
270
271 Here we've implicitly defined a [cmd tag] method which has two
272 subcommands, [cmd configure] and [cmd cget].
273
274 [para]
275
276 In Snit 1.3, hierarchical methods could be called in two ways:
277
278 [example {$obj tag cget -myoption      ;# The good way
279 $obj {tag cget} -myoption    ;# The weird way
280 }]
281
282 In the second call, we see that a hierarchical method or type method
283 is simply one whose name contains multiple words.
284
285 [para]
286
287 In Snit 2.2 this is no longer the case, and the "weird" way of calling
288 hierarchical methods and type methods no longer works.
289
290 [item]
291 The third incompatibility derives from the second.  In Snit 1.3,
292 hierarchical methods were also simply methods whose name contains
293 multiple words.  As a result, [cmd "\$obj info methods"] returned the
294 full names of all hierarchical methods.  In the example above, 
295 the list returned by [cmd "\$obj info methods"] would include
296 [cmd "tag configure"] and [cmd "tag cget"] but not [cmd "tag"], since
297 [cmd "tag"] is defined only implicitly.
298
299 [para]
300
301 In Snit 2.2, hierarchical methods and type methods are no longer
302 simply ones whose
303 name contains multiple words; in the above example, the list returned
304 by [cmd "\$obj info methods"] would include [cmd "tag"] but not
305 [cmd "tag configure"] or [cmd "tag cget"].
306
307
308 [item]
309 The fourth incompatibility is due to a new feature.  Snit 2.2 uses
310 the new [cmd "namespace path"] command so that a type's code can 
311 call any command defined in the type's parent namespace without
312 qualification or importation.  For example, suppose you have a 
313 package called [cmd "mypackage"] which defines a number of commands
314 including a type, [cmd "::mypackage::mytype"].  Thanks to 
315 [cmd "namespace path"], the type's code can call any of the other
316 commands defined in [cmd "::mypackage::"].
317
318 [para]
319
320 This is extremely convenient.  However, it also means that commands
321 defined in the parent namespace, [cmd "::mypackage::"] can block the
322 type's access to identically named commands in the global namespace.
323 This can lead to bugs.  For example, Tcllib includes a type called
324 [cmd "::tie::std::file"].  This type's code calls the standard
325 [cmd "file"] command.  When run with Snit 2.2, the code broke--
326 the type's command, [cmd "::tie::std::file"], is itself a command
327 in the type's parent namespace, and so instead of calling 
328 the standard [cmd "file"] command, the type found itself calling
329 itself.
330
331 [list_end]
332
333 [subsection {Are there other differences between Snit 1.x and Snit 2.2?}]
334
335 Yes.
336
337 [list_begin itemized]
338 [item]
339 Method dispatch is considerably faster.
340
341 [item]
342 Many error messages and stack traces are cleaner.
343
344 [item]
345 The [const -simpledispatch] pragma is obsolete, and ignored if
346 present. In Snit 1.x, [const -simpledispatch] substitutes a faster
347 mechanism for method dispatch, at the cost of losing certain features.
348 Snit 2.2 method dispatch is faster still in all cases, so 
349 [const -simpledispatch] is no longer needed.
350
351 [item]
352
353 In Snit 2.2, a type's code (methods, type methods, etc.) can call commands
354 from the type's parent namespace without qualifying or importing
355 them, i.e., type [cmd ::parentns::mytype]'s code can call
356 [cmd ::parentns::someproc] as just [cmd someproc].
357
358 [para]
359
360 This is extremely useful when a type is defined as part of a larger
361 package, and shares a parent namespace with the rest of the package;
362 it means that the type can call other commands defined by the
363 package without any extra work.
364
365 [para]
366
367 This feature depends on the new Tcl 8.5 [cmd "namespace path"] command,
368 which is why it hasn't been implemented for V1.x.  V1.x code can
369 achieve something similar by placing
370
371 [example {namespace import [namespace parent]::*}]
372
373 in a type constructor.  This is less useful, however, as it picks up
374 only those commands which have already been exported by the parent
375 namespace at the time the type is defined.
376
377 [list_end]
378
379
380 [section OBJECTS]
381
382 [subsection {What is an object?}]
383
384 A full description of object-oriented programming is beyond
385 the scope of this FAQ, obviously.  In simple terms, an object is an instance of
386 an abstract data type--a coherent bundle of code and data.
387 There are many ways to represent objects in Tcl/Tk; the best known
388 examples are the Tk widgets.
389
390 [para]
391
392 A Tk widget is an object; it is represented by a Tcl command.  
393 The object's methods are subcommands of the Tcl command.  The object's
394 properties are options accessed using the [method configure] and 
395 [method cget] methods.  Snit uses the same conventions as Tk widgets do.
396
397 [subsection {What is an abstract data type?}]
398
399 In computer science terms, an abstract data type is a complex data
400 structure along with a set of operations--a stack, a queue, a
401 binary tree, etc--that is to say, in modern terms, an object.  In systems
402 that include some form of inheritance the word [term class] is
403 usually used instead of [term {abstract data type}], but as Snit
404 doesn't implement inheritance as it's ordinarily understood
405 the older term seems more appropriate.  Sometimes this is called 
406 [term {object-based}] programming as opposed to object-oriented
407 programming.  Note that you can easily create the effect of 
408 inheritance using [sectref COMPONENTS] and [sectref "DELEGATION"].
409
410 [para]
411
412 In Snit, as in Tk, a [term type] is a command that creates instances
413 -- objects -- which belong to the type.  Most types define some number
414 of [term options] which can be set at creation time, and usually can be
415 changed later.
416
417 [para]
418
419 Further, an [term instance] is also a Tcl command--a command that
420 gives access to the operations which are defined for that abstract
421 data type.  Conventionally, the operations are defined as subcommands
422 of the instance command.  For example, to insert
423 text into a Tk text widget, you use the text widget's [method insert]
424 subcommand:
425
426 [para]
427 [example {    # Create a text widget and insert some text in it.
428     text .mytext -width 80 -height 24
429     .mytext insert end "Howdy!"
430 }]
431 [para]
432
433 In this example, [cmd text] is the [term type] command and
434 [cmd .mytext] is the [term instance] command.
435
436 [para]
437
438 In Snit, object subcommands are generally called 
439 [sectref "INSTANCE METHODS"].
440
441 [subsection {What kinds of abstract data types does Snit provide?}]
442
443 Snit allows you to define three kinds of abstract data type:
444
445 [para]
446
447 [list_begin itemized]
448 [item]
449
450 [cmd snit::type]
451 [item]
452
453 [cmd snit::widget]
454 [item]
455
456 [cmd snit::widgetadaptor]
457 [list_end]
458
459
460 [subsection {What is a snit::type?}]
461
462 A [cmd snit::type] is a non-GUI abstract data type, e.g., a stack or a
463 queue.  [cmd snit::type]s are defined using the [cmd snit::type]
464 command.  For example, if you were designing a kennel management
465 system for a dog breeder, you'd need a dog type.
466
467 [para]
468 [example {% snit::type dog {
469     # ...
470 }
471 ::dog
472 %
473 }]
474 [para]
475
476 This definition defines a new command ([cmd ::dog], in this case)
477 that can be used to define dog objects.
478
479 [para]
480
481 An instance of a [cmd snit::type] can have [sectref {INSTANCE METHODS}],
482 [sectref {INSTANCE VARIABLES}], [sectref OPTIONS], and [sectref COMPONENTS].
483 The type itself can have [sectref {TYPE METHODS}],
484 [sectref {TYPE VARIABLES}], [sectref {TYPE COMPONENTS}], and 
485 [sectref PROCS]. 
486
487
488 [subsection {What is a snit::widget?, the short story}]
489
490 A [cmd snit::widget] is a Tk megawidget built using Snit; it is very
491 similar to a [cmd snit::type].  See [sectref WIDGETS].
492
493
494 [subsection {What is a snit::widgetadaptor?, the short story}]
495
496 A [cmd snit::widgetadaptor] uses Snit to wrap an existing widget type
497 (e.g., a Tk label), modifying its interface to a lesser or greater
498 extent.  It is very similar to a [cmd snit::widget].
499 See [sectref {WIDGET ADAPTORS}].
500
501
502 [subsection {How do I create an instance of a snit::type?}]
503
504 You create an instance of a [cmd snit::type] by passing the new
505 instance's name to the type's create method.  In the following
506 example, we create a [cmd dog] object called [cmd spot].
507
508 [para]
509 [example {% snit::type dog {
510     # ....
511 }
512 ::dog
513 % dog create spot
514 ::spot
515 %
516 }]
517 [para]
518
519 In general, the [method create] method name can be omitted so long as
520 the instance name doesn't conflict with any defined 
521 [sectref {TYPE METHODS}]. (See [sectref {TYPE COMPONENTS}] for the
522 special case in which this doesn't work.)
523 So the following example is identical to the
524 previous example:
525
526 [para]
527 [example {% snit::type dog {
528     # ....
529 }
530 ::dog
531 % dog spot
532 ::spot
533 %
534 }]
535 [para]
536
537 This document generally uses the shorter form.
538
539 [para]
540
541 If the [cmd dog] type defines [sectref OPTIONS], these can usually be 
542 given defaults at creation time:
543
544 [para]
545 [example {% snit::type dog {
546     option -breed mongrel
547     option -color brown
548
549     method bark {} { return "$self barks." }
550 }
551 ::dog
552 % dog create spot -breed dalmation -color spotted
553 ::spot
554 % spot cget -breed
555 dalmation
556 % spot cget -color
557 spotted
558 %
559 }]
560 [para]
561
562 Once created, the instance name now names a new Tcl command that is used
563 to manipulate the object.  For example, the following code makes the
564 dog bark:
565
566 [para]
567 [example {% spot bark
568 ::spot barks.
569 %
570 }]
571 [para]
572
573 [subsection {How do I refer to an object indirectly?}]
574
575 Some programmers prefer to save the object name in a variable, and
576 reference it that way.  For example,
577
578 [para]
579 [example {% snit::type dog { ... }
580 ::dog
581 % set d [dog spot -breed dalmation -color spotted]
582 ::spot
583 % $d cget -breed
584 dalmation
585 % $d bark
586 ::spot barks.
587 %
588 }]
589 [para]
590
591 If you prefer this style, you might prefer to have Snit
592 generate the instance's name automatically.
593
594 [subsection {How can I generate the object name automatically?}]
595
596 If you'd like Snit to generate an object name for you,
597 use the [const %AUTO%] keyword as the requested name:
598
599 [para]
600 [example {% snit::type dog { ... }
601 ::dog
602 % set d [dog %AUTO%]
603 ::dog2
604 % $d bark
605 ::dog2 barks.
606 %
607 }]
608 [para]
609
610 The [const %AUTO%] keyword can be embedded in a longer string:
611
612 [para]
613 [example {% set d [dog obj_%AUTO%]
614 ::obj_dog4
615 % $d bark
616 ::obj_dog4 barks.
617 %
618 }]
619 [para]
620
621
622 [subsection {Can types be renamed?}]
623
624 Tcl's [cmd rename] command renames other commands.  It's a common
625 technique in Tcl to modify an existing command by renaming it and
626 defining a new command with the original name; the new command usually
627 calls the renamed command.
628
629 [para]
630
631 [cmd snit::type] commands, however, should never be renamed; to do so breaks
632 the connection between the type and its objects.
633
634 [subsection {Can objects be renamed?}]
635
636 Tcl's [cmd rename] command renames other commands.  It's a common
637 technique in Tcl to modify an existing command by renaming it and
638 defining a new command with the original name; the new command usually
639 calls the renamed command.
640
641 [para]
642
643 All Snit objects (including [term widgets] and [term widgetadaptors])
644 can be renamed, though this flexibility has some consequences:
645
646 [para]
647
648 [list_begin itemized]
649 [item]
650
651 In an instance method, the implicit argument [var self] will always
652 contain the object's current name, so instance methods can always call
653 other instance methods using [var \$self].
654
655 [item]
656
657 If the object is renamed, however, then [var \$self]'s value will change.
658 Therefore, don't use [var \$self] for anything that will break if 
659 [var \$self] changes. For example, don't pass a callback command to
660 another object like this:
661
662 [example {
663     .btn configure -command [list $self ButtonPress]
664 }]
665
666 You'll get an error if [cmd .btn] calls your command after your object is
667 renamed.
668
669 [item]
670
671 Instead, your object should define its callback command like this:
672
673 [example {
674     .btn configure -command [mymethod ButtonPress]
675 }]
676
677 The [cmd mymethod] command returns code that will call the desired
678 method safely; the caller of the callback can add additional
679 arguments to the end of the command as usual.
680
681 [item]
682
683 Every object has a private namespace; the name of this namespace is
684 available in method bodies, etc., as the value of the implicit
685 argument [var selfns].  This value is constant for the life of the
686 object.  Use [var \$selfns] instead of [var \$self] if you need a 
687 unique token to identify the object.
688
689 [item]
690
691 When a [cmd snit::widget]'s instance command is renamed, its Tk window
692 name remains the same -- and is still extremely
693 important. Consequently, the Tk window name is available in 
694 method bodies as the value of the implicit argument [var win].  
695 This value is constant for the
696 life of the object.  When creating child windows, it's best to use
697 [var {$win.child}] rather than [var {$self.child}] as the name of the
698 child window.
699
700 [list_end]
701
702 [subsection {How do I destroy a Snit object?}]
703
704 Any Snit object of any type can be destroyed by renaming
705 it to the empty string using the Tcl [cmd rename] command.
706
707 [para]
708
709 Snit megawidgets (i.e., instances of [cmd snit::widget] and
710 [cmd snit::widgetadaptor]) can be destroyed like any other widget: by
711 using the Tk [cmd destroy] command on the widget or on one of its
712 ancestors in the window hierarchy.
713
714 [para]
715
716 Every instance of a [cmd snit::type] has a [method destroy] method:
717
718 [para]
719 [example {% snit::type dog { ... }
720 ::dog
721 % dog spot
722 ::spot
723 % spot bark
724 ::spot barks.
725 % spot destroy
726 % spot barks
727 invalid command name "spot"
728 %
729 }]
730 [para]
731
732 Finally, every Snit type has a type method called [method destroy]; calling it
733 destroys the type and all of its instances:
734
735 [example {% snit::type dog { ... }
736 ::dog
737 % dog spot
738 ::spot
739 % spot bark
740 ::spot barks.
741 % dog destroy
742 % spot bark
743 invalid command name "spot"
744 % dog fido
745 invalid command name "dog"
746 %
747 }]
748
749 [section {INSTANCE METHODS}]
750
751 [subsection {What is an instance method?}]
752
753 An instance method is a procedure associated with a specific object
754 and called as a subcommand of the object's command.  It is given free
755 access to all of the object's type variables, instance variables, and
756 so forth.
757
758 [subsection {How do I define an instance method?}]
759
760 Instance methods are defined in the type definition using
761 the [cmd method] statement.  Consider the following code that might be
762 used to add dogs to a computer simulation:
763
764 [para]
765 [example {% snit::type dog {
766     method bark {} {
767         return "$self barks."
768     }
769
770     method chase {thing} {
771         return "$self chases $thing."
772     }
773 }
774 ::dog
775 %
776 }]
777 [para]
778
779 A dog can bark, and it can chase things.
780
781 [para]
782
783 The [cmd method] statement looks just like a normal Tcl [cmd proc],
784 except that it appears in a [cmd snit::type] definition.  Notice that
785 every instance method gets an implicit argument called [var self];
786 this argument contains the object's name.  (There's more on
787 implicit method arguments below.)
788
789 [subsection {How does a client call an instance method?}]
790
791 The method name becomes a subcommand of the object.  For example,
792 let's put a simulated dog through its paces:
793
794 [para]
795 [example {% dog spot
796 ::spot
797 % spot bark
798 ::spot barks.
799 % spot chase cat
800 ::spot chases cat.
801 %
802 }]
803 [para]
804
805 [subsection {How does an instance method call another instance method?}]
806
807 If method A needs to call method B on the same object, it does so just
808 as a client does: it calls method B as a subcommand of the object
809 itself, using the object name stored in the implicit argument [var self].
810
811 [para]
812
813 Suppose, for example, that our dogs never chase anything without
814 barking at them:
815
816 [para]
817 [example {% snit::type dog {
818     method bark {} {
819         return "$self barks."
820     }
821
822     method chase {thing} {
823         return "$self chases $thing.  [$self bark]"
824     }
825 }
826 ::dog
827 % dog spot
828 ::spot
829 % spot bark
830 ::spot barks.
831 % spot chase cat
832 ::spot chases cat.  ::spot barks.
833 %
834 }]
835 [para]
836
837 [subsection {Are there any limitations on instance method names?}]
838
839 Not really, so long as you avoid the standard instance method names:
840 [method configure], [method configurelist], [method cget],
841 [method destroy], and [method info].  Also, method names consisting of 
842 multiple words define hierarchical methods.
843
844 [subsection {What is a hierarchical method?}]
845
846 An object's methods are subcommands of the object's instance command.
847 Hierarchical methods allow an object's methods to have subcommands of
848 their own; and these can in turn have subcommands, and so on.  This
849 allows the programmer to define a tree-shaped command structure, such
850 as is used by many of the Tk widgets--the subcommands of the 
851 Tk [cmd text] widget's [cmd tag] method are hierarchical methods.
852
853 [subsection {How do I define a hierarchical method?}]
854
855 Define methods whose names consist of multiple words.  These words
856 define the hierarchy implicitly.  For example, the following code
857 defines a [cmd tag] method with subcommands [cmd cget] and 
858 [cmd configure]:
859
860 [example {snit::widget mytext {
861     method {tag configure} {tag args} { ... }
862
863     method {tag cget} {tag option} {...}
864 }
865 }]
866
867 Note that there is no explicit definition for the [cmd tag] method;
868 it is implicit in the definition of [cmd "tag configure"] and
869 [cmd "tag cget"].  If you tried to define [cmd tag] explicitly in this
870 example, you'd get an error.
871
872 [subsection {How do I call hierarchical methods?}]
873
874 As subcommands of subcommands.
875
876 [example {% mytext .text
877 .text
878 % .text tag configure redtext -foreground red -background black
879 % .text tag cget redtext -foreground
880 red
881 %
882 }]
883
884 [subsection {How do I make an instance method private?}]
885
886 It's often useful to define private methods, that is, instance methods
887 intended to be called only by other methods of the same object.
888
889 [para]
890
891 Snit doesn't implement any access control on instance methods, so all
892 methods are [emph {de facto}] public.  Conventionally, though, the
893 names of public methods begin with a lower-case letter, and the names
894 of private methods begin with an upper-case letter.
895
896 [para]
897
898 For example, suppose our simulated dogs only bark in response to other
899 stimuli; they never bark just for fun.  So the [method bark] method
900 becomes [method Bark] to indicate that it is private:
901
902 [para]
903 [example {% snit::type dog {
904     # Private by convention: begins with uppercase letter.
905     method Bark {} {
906         return "$self barks."
907     }
908
909     method chase {thing} {
910         return "$self chases $thing. [$self Bark]"
911     }
912 }
913 ::dog
914 % dog fido
915 ::fido
916 % fido chase cat
917 ::fido chases cat. ::fido barks.
918 %
919 }]
920 [para]
921
922 [subsection {Are there any limitations on instance method arguments?}]
923
924 Method argument lists are defined just like normal Tcl [cmd proc] argument
925 lists; in particular, they can include arguments with default values
926  and the [var args] argument.
927
928 [para]
929
930 However, every method also has a number of implicit arguments
931 provided by Snit in addition to those explicitly defined.  The names
932 of these implicit arguments may not used to name explicit arguments.
933
934 [subsection {What implicit arguments are passed to each instance method?}]
935
936 The arguments implicitly passed to every method are [var type],
937 [var selfns], [var win], and [var self].
938
939 [subsection {What is $type?}]
940
941 The implicit argument [var type] contains the fully qualified name of
942 the object's type:
943
944 [para]
945 [example {% snit::type thing {
946     method mytype {} {
947         return $type
948     }
949 }
950 ::thing
951 % thing something
952 ::something
953 % something mytype
954 ::thing
955 %
956 }]
957 [para]
958
959 [subsection {What is $self?}]
960
961 The implicit argument [var self] contains the object's fully
962 qualified name.
963
964 [para]
965
966 If the object's command is renamed, then [var \$self] will change to
967 match in subsequent calls.  Thus, your code should not assume that
968 [var \$self] is constant unless you know for sure that the object
969 will never be renamed.
970
971 [para]
972 [example {% snit::type thing {
973     method myself {} {
974         return $self
975     }
976 }
977 ::thing
978 % thing mutt
979 ::mutt
980 % mutt myself
981 ::mutt
982 % rename mutt jeff
983 % jeff myself
984 ::jeff
985 %
986 }]
987 [para]
988
989 [subsection {What is $selfns?}]
990
991 Each Snit object has a private namespace in which to store its
992 [sectref {INSTANCE VARIABLES}] and [sectref OPTIONS].  The implicit argument
993 [var selfns] contains the name of this namespace; its value never changes, and
994 is constant for the life of the object, even if the object's name
995 changes:
996
997 [para]
998 [example {% snit::type thing {
999     method myNameSpace {} {
1000         return $selfns
1001     }
1002 }
1003 ::thing
1004 % thing jeff
1005 ::jeff
1006 % jeff myNameSpace
1007 ::thing::Snit_inst3
1008 % rename jeff mutt
1009 % mutt myNameSpace
1010 ::thing::Snit_inst3
1011 %
1012 }]
1013 [para]
1014
1015 The above example reveals how Snit names an instance's private
1016 namespace; however, you should not write code that depends on the
1017 specific naming convention, as it might change in future releases.
1018
1019 [subsection {What is $win?}]
1020
1021 The implicit argument [var win] is defined for all Snit methods,
1022 though it really makes sense only for those of 
1023 [sectref WIDGETS] and [sectref {WIDGET ADAPTORS}].  [var \$win] is simply
1024 the original name of the object, whether it's been renamed or not.
1025 For widgets and widgetadaptors, it is also therefore the name of a Tk
1026 window.
1027
1028 [para]
1029
1030 When a [cmd snit::widgetadaptor] is used to modify the interface of a
1031 widget or megawidget, it must rename the widget's original command and
1032 replace it with its own.
1033
1034 [para]
1035
1036 Thus, using [var win] whenever the Tk window name is called for
1037 means that a [cmd snit::widget] or [cmd snit::widgetadaptor] can be
1038 adapted by a [cmd snit::widgetadaptor].  See [sectref WIDGETS] for
1039 more information.
1040
1041 [subsection {How do I pass an instance method as a callback?}]
1042
1043 It depends on the context.
1044
1045 [para]
1046
1047 Suppose in my application I have a [cmd dog] object named [cmd fido],
1048 and I want [cmd fido] to bark when a Tk button called [cmd .bark] is 
1049 pressed.  In this case, I create the callback command in the usual
1050 way, using [cmd list]:
1051
1052 [para]
1053 [example {    button .bark -text "Bark!" -command [list fido bark]
1054 }]
1055 [para]
1056
1057 In typical Tcl style, we use a callback to hook two independent
1058 components together.  But suppose that the [cmd dog] object has
1059 a graphical interface and owns the button itself?  In this case,
1060 the [cmd dog] must pass one of its own instance methods to the
1061 button it owns.  The obvious thing to do is this:
1062
1063 [para]
1064 [example {% snit::widget dog {
1065     constructor {args} {
1066         #...
1067         button $win.barkbtn -text "Bark!" -command [list $self bark]
1068         #...
1069     }
1070 }
1071 ::dog
1072 %
1073 }]
1074 [para]
1075
1076 (Note that in this example, our [cmd dog]
1077 becomes a [cmd snit::widget], because it has GUI behavior.  See
1078 [sectref WIDGETS] for more.)  Thus, if we create a [cmd dog] called
1079 [cmd .spot], it will create a Tk button called [cmd .spot.barkbtn];
1080 when pressed, the button will call [cmd {$self bark}].
1081
1082 [para]
1083
1084 Now, this will work--provided that [cmd .spot] is never renamed to
1085 something else.  But surely renaming widgets is
1086 abnormal?  And so it is--unless [cmd .spot] is the hull component of a
1087 [cmd snit::widgetadaptor].  If it is, then it will be renamed, and
1088 [cmd .spot] will become the name of the [cmd snit::widgetadaptor]
1089 object.  When the button is pressed, the command [cmd {$self bark}]
1090 will be handled by the [cmd snit::widgetadaptor], which might or might
1091 not do the right thing.
1092
1093 [para]
1094
1095 There's a safer way to do it, and it looks like this:
1096
1097 [para]
1098 [example {% snit::widget dog {
1099     constructor {args} {
1100         #...
1101         button $win.barkbtn -text "Bark!" -command [mymethod bark]
1102         #...
1103     }
1104 }
1105 ::dog
1106 %
1107 }]
1108 [para]
1109
1110 The command [cmd mymethod] takes any number of arguments, and can be
1111 used like [cmd list] to build up a callback command; the only
1112 difference is that [cmd mymethod] returns a 
1113 form of the command that won't change even if the instance's name
1114 changes.
1115
1116 [para]
1117
1118 On the other hand, you might prefer to allow a widgetadaptor to 
1119 override a method such that your renamed widget will call the
1120 widgetadaptor's method instead of its own.  In this case, 
1121 using [cmd "\[list \$self bark\]"] will do what you want...but
1122 this is a technique which should be used only in carefully controlled
1123 circumstances.
1124
1125 [subsection {How do I delegate instance methods to a component?}]
1126
1127 See [sectref DELEGATION].
1128
1129 [section {INSTANCE VARIABLES}]
1130
1131
1132 [subsection {What is an instance variable?}]
1133
1134 An instance variable is a private variable associated with some
1135 particular Snit object.  Instance variables can be scalars or arrays.
1136
1137
1138 [subsection {How is a scalar instance variable defined?}]
1139
1140 Scalar instance variables are defined in the type definition using the
1141 [cmd variable] statement.  You can simply name it, or you can
1142 initialize it with a value:
1143
1144 [para]
1145 [example {snit::type mytype {
1146     # Define variable "greeting" and initialize it with "Howdy!"
1147     variable greeting "Howdy!"
1148 }
1149 }]
1150 [para]
1151
1152 [subsection {How is an array instance variable defined?}]
1153
1154 Array instance variables are also defined in the type definition
1155 using the [cmd variable] command.  You can initialize them at the same
1156 time by specifying the [const -array] option:
1157
1158 [para]
1159 [example {snit::type mytype {
1160     # Define array variable "greetings"
1161     variable greetings -array {
1162         formal "Good Evening"
1163         casual "Howdy!"
1164     }
1165 }
1166 }]
1167 [para]
1168
1169 [subsection {What happens if I don't initialize an instance variable?}]
1170
1171 Variables do not really exist until they are given values.  If you 
1172 do not initialize a variable when you define it, then you must be
1173 sure to assign a value to it (in the constructor, say, or in some
1174 method) before you reference it.
1175
1176 [subsection {Are there any limitations on instance variable names?}]
1177
1178 Just a few.
1179
1180 [para]
1181
1182 First, every Snit object has a built-in instance variable called
1183 [var options], which should never be redefined.
1184
1185 [para]
1186
1187 Second, all names beginning with "Snit_" are reserved for
1188 use by Snit internal code.
1189
1190 [para]
1191
1192 Third, instance variable names containing the namespace delimiter
1193 ([const ::]) are likely to cause great confusion.
1194
1195
1196 [subsection {Do I need to declare my instance variables in my methods?}]
1197
1198 No. Once you've defined an instance variable in the type definition,
1199 it can be used in any instance code (instance methods, the
1200 constructor, and the destructor) without declaration.  This differs
1201 from normal Tcl practice, in which all non-local variables in a proc
1202 need to be declared.
1203
1204 [para]
1205
1206 There is a speed penalty to having all instance variables implicitly
1207 available in all instance code.  Even though your code need not 
1208 declare the variables explicitly, Snit must still declare them,
1209 and that takes time.  If you have ten instance variables, a method
1210 that uses none of them must still pay the declaration penalty for 
1211 all ten.  In most cases, the additional runtime cost is negligible.
1212 If extreme cases, you might wish to avoid it; there are two methods
1213 for doing so.
1214
1215 [para]
1216
1217 The first is to define a single instance variable, an array, and store
1218 all of your instance data in the array.  This way, you're only paying
1219 the declaration penalty for one variable--and you probably need the
1220 variable most of the time anyway.  This method breaks down if your
1221 instance variables include multiple arrays; in Tcl 8.5, however,
1222 the [cmd dict] command might come to your rescue.
1223
1224 [para]
1225
1226 The second method is to declare your instance variables explicitly
1227 in your instance code, while [emph not] including them in the type
1228 definition:
1229
1230 [example {snit::type dog {
1231     constructor {} {
1232         variable mood
1233
1234         set mood happy
1235     }
1236
1237     method setmood {newMood} {
1238         variable mood
1239
1240         set mood $newMood
1241     }
1242
1243     method getmood {} {
1244         variable mood
1245
1246         return $mood
1247     }
1248 }
1249 }]
1250
1251 This allows you to ensure that only the required variables are
1252 included in each method, at the cost of longer code and run-time
1253 errors when you forget to declare a variable you need.
1254
1255 [subsection {How do I pass an instance variable's name to another object?}]
1256
1257 In Tk, it's common to pass a widget a variable name; for example, Tk
1258 label widgets have a [option -textvariable] option which names the
1259 variable which will contain the widget's text.  This allows the
1260 program to update the label's value just by assigning a new value to
1261 the variable.
1262
1263 [para]
1264
1265 If you naively pass the instance variable name to the label widget,
1266 you'll be confused by the result; Tk will assume that the name names a
1267 global variable.  Instead, you need to provide a fully-qualified
1268 variable name.  From within an instance method or a constructor, you
1269 can fully qualify the variable's name using the [cmd myvar] command:
1270
1271 [para] 
1272 [example {snit::widget mywidget {
1273     variable labeltext ""
1274
1275     constructor {args} {
1276         # ...
1277
1278         label $win.label -textvariable [myvar labeltext]
1279
1280         # ...
1281     }
1282 }
1283 }]
1284 [para]
1285
1286 [subsection {How do I make an instance variable public?}]
1287
1288 Practically speaking, you don't.  Instead, you'll implement public
1289 variables as [sectref OPTIONS].
1290
1291 Alternatively, you can write [sectref {INSTANCE METHODS}] to set and get
1292 the variable's value.
1293
1294 [section OPTIONS]
1295
1296 [subsection {What is an option?}]
1297
1298 A type's options are the equivalent of what other object-oriented
1299 languages would call public member variables or properties: they are
1300 data values which can be retrieved and (usually) set by the clients of
1301 an object.
1302
1303 [para]
1304
1305 Snit's implementation of options follows the Tk model fairly exactly,
1306 except that [cmd snit::type] objects usually don't interact with 
1307 [sectref "THE TK OPTION DATABASE"]; [cmd snit::widget] and 
1308 [cmd snit::widgetadaptor] objects, on the other hand, always do.
1309
1310 [subsection {How do I define an option?}]
1311
1312 Options are defined in the type definition using the [cmd option]
1313 statement.  Consider the following type, to be used in an application
1314 that manages a list of dogs for a pet store:
1315
1316 [para]
1317 [example {snit::type dog {
1318     option -breed -default mongrel
1319     option -color -default brown
1320     option -akc   -default 0
1321     option -shots -default 0
1322 }
1323 }]
1324 [para]
1325
1326
1327 According to this, a dog has four notable properties: a
1328 breed, a color, a flag that says whether it's pedigreed with the
1329 American Kennel Club, and another flag that says whether it has had
1330 its shots.  The default dog, evidently, is a brown mutt.
1331
1332 [para]
1333
1334 There are a number of options you can specify when defining an option;
1335 if [const -default] is the only one, you can omit the word 
1336 [const -default] as follows:
1337
1338 [para]
1339 [example {snit::type dog {
1340     option -breed mongrel
1341     option -color brown
1342     option -akc   0
1343     option -shots 0
1344 }
1345 }]
1346
1347 [para]
1348
1349 If no [const -default] value is specified, the option's default value
1350 will be the empty string (but see [sectref {THE TK OPTION DATABASE}]).
1351
1352 [para]
1353
1354 The Snit man page refers to options like these as "locally defined" options.
1355
1356 [subsection {How can a client set options at object creation?}]
1357
1358 The normal convention is that the client may pass any number of
1359 options and their values after the object's name at object creation.
1360 For example, the [cmd ::dog] command defined in the previous answer can now
1361 be used to create individual dogs.  Any or all of the options may be
1362 set at creation time.
1363
1364 [para]
1365 [example {% dog spot -breed beagle -color "mottled" -akc 1 -shots 1
1366 ::spot
1367 % dog fido -shots 1
1368 ::fido
1369 %
1370 }]
1371 [para]
1372
1373 So [cmd ::spot] is a pedigreed beagle; [cmd ::fido] is a typical mutt,
1374 but his owners evidently take care of him, because he's had his shots.
1375
1376 [para]
1377
1378 [emph Note:] If the type defines a constructor, it can specify a
1379 different object-creation syntax.  See [sectref CONSTRUCTORS] for more
1380 information.
1381
1382 [subsection {How can a client retrieve an option's value?}]
1383
1384 Retrieve option values using the [method cget] method:
1385
1386 [para]
1387 [example {% spot cget -color
1388 mottled
1389 % fido cget -breed
1390 mongrel
1391 %
1392 }]
1393 [para]
1394
1395 [subsection {How can a client set options after object creation?}]
1396
1397 Any number of options may be set at one time using the
1398 [method configure] instance method.  Suppose that closer inspection
1399 shows that ::fido is not a brown mongrel, but rather a rare Arctic Boar 
1400 Hound of a lovely dun color:
1401
1402 [para]
1403 [example {% fido configure -color dun -breed "Arctic Boar Hound"
1404 % fido cget -color
1405 dun
1406 % fido cget -breed
1407 Arctic Boar Hound
1408 }]
1409 [para]
1410
1411 Alternatively, the [method configurelist] method takes a list of
1412 options and values; occasionally this is more convenient:
1413
1414 [para]
1415 [example {% set features [list -color dun -breed "Arctic Boar Hound"]
1416 -color dun -breed {Arctic Boar Hound}
1417 % fido configurelist $features
1418 % fido cget -color
1419 dun
1420 % fido cget -breed
1421 Arctic Boar Hound
1422 %
1423 }]
1424 [para]
1425
1426 In Tcl 8.5, the [cmd {*}] keyword can be used with 
1427 [method configure] in this case:
1428
1429 [para]
1430 [example {% set features [list -color dun -breed "Arctic Boar Hound"]
1431 -color dun -breed {Arctic Boar Hound}
1432 % fido configure {*}$features
1433 % fido cget -color
1434 dun
1435 % fido cget -breed
1436 Arctic Boar Hound
1437 %
1438 }]
1439 [para]
1440
1441 The results are the same.
1442
1443 [subsection {How should an instance method access an option value?}]
1444
1445 There are two ways an instance method can set and retrieve an option's
1446 value.  One is to use the [method configure] and [method cget]
1447 methods, as shown below.
1448
1449 [para]
1450 [example {% snit::type dog {
1451     option -weight 10
1452
1453     method gainWeight {} {
1454         set wt [$self cget -weight]
1455         incr wt
1456         $self configure -weight $wt
1457     }
1458 }
1459 ::dog
1460 % dog fido
1461 ::fido
1462 % fido cget -weight
1463 10
1464 % fido gainWeight
1465 % fido cget -weight
1466 11
1467 %
1468 }]
1469 [para]
1470
1471 Alternatively, Snit provides a built-in array instance variable called
1472 [var options].  The indices are the option names; the values are the
1473 option values.  The method [method gainWeight] can thus be rewritten as
1474 follows:
1475
1476 [para]
1477 [example {
1478     method gainWeight {} {
1479         incr options(-weight)
1480     }
1481 }]
1482 [para]
1483
1484 As you can see, using the [var options] variable involves considerably
1485 less typing and is the usual way to do it.  But if you use 
1486 [const -configuremethod] or [const -cgetmethod] (described in the following
1487 answers), you might wish to use the [method configure] and 
1488 [method cget] methods anyway, just so that any special processing you've
1489 implemented is sure to get done.  Also, if the option is delegated to
1490 a component then [method configure] and [method cget] are the only way
1491 to access it without accessing the component directly.  See 
1492 [sectref "DELEGATION"] for more information.
1493
1494 [subsection {How can I make an option read-only?}]
1495
1496 Define the option with [const "-readonly yes"].
1497
1498 [para]
1499
1500 Suppose you've got an option that determines how
1501 instances of your type are constructed; it must be set at creation
1502 time, after which it's constant.  For example, a dog never changes its
1503 breed; it might or might not have had its shots, and if not can have
1504 them at a later time.  [const -breed] should be read-only, but
1505 [const -shots] should not be.
1506
1507 [para]
1508 [example {% snit::type dog {
1509     option -breed -default mongrel -readonly yes
1510     option -shots -default no
1511 }
1512 ::dog
1513 % dog fido -breed retriever
1514 ::fido
1515 % fido configure -shots yes
1516 % fido configure -breed terrier
1517 option -breed can only be set at instance creation
1518 %
1519 }]
1520 [para]
1521
1522 [subsection {How can I catch accesses to an option's value?}]
1523
1524 Define a [const -cgetmethod] for the option.
1525
1526 [subsection {What is a -cgetmethod?}]
1527
1528 A [const -cgetmethod] is a method that's called whenever the related
1529 option's value is queried via the 
1530 [method cget] instance method.  The handler can compute the option's
1531 value, retrieve it from a database, or do anything else you'd like it to do.
1532
1533 [para]
1534
1535 Here's what the default behavior would look like if
1536 written using a [const -cgetmethod]:
1537
1538 [para]
1539 [example {snit::type dog {
1540     option -color -default brown -cgetmethod GetOption
1541
1542     method GetOption {option} {
1543         return $options($option)
1544     }
1545 }
1546 }]
1547 [para]
1548
1549 Any instance method can be used, provided that it takes one argument,
1550 the name of the option whose value is to be retrieved.
1551
1552 [subsection {How can I catch changes to an option's value?}]
1553
1554 Define a [const -configuremethod] for the option.
1555
1556 [subsection {What is a -configuremethod?}]
1557
1558 A [const -configuremethod] is a method that's called whenever the
1559 related option is given a new value via the [method configure] or
1560 [method configurelist] instance methods. The method can 
1561 pass the value on to some other object, store it in a database, or do
1562 anything else you'd like it to do.
1563
1564 [para]
1565
1566 Here's what the default configuration behavior would look like if
1567 written using a [const -configuremethod]:
1568
1569 [para]
1570 [example {snit::type dog {
1571     option -color -default brown -configuremethod SetOption
1572
1573     method SetOption {option value} {
1574         set options($option) $value
1575     }
1576 }
1577 }]
1578 [para]
1579
1580 Any instance method can be used, provided that it takes two arguments,
1581 the name of the option and the new value.
1582
1583 [para]
1584
1585 Note that if your method doesn't store the value in the [var options]
1586 array, the [var options] array won't get updated.
1587
1588 [subsection {How can I validate an option's value?}]
1589
1590 Define a [const -validatemethod].
1591
1592 [subsection {What is a -validatemethod?}]
1593
1594 A [const -validatemethod] is a method that's called whenever the
1595 related option is given a new value via the [method configure] or
1596 [method configurelist] instance methods.  It's the method's
1597 responsibility to determine whether the new value is valid, and throw
1598 an error if it isn't.  The [const -validatemethod], if any, is called
1599 before the value is stored in the [var options] array; in particular,
1600 it's called before the [const -configuremethod], if any.
1601
1602 [para]
1603
1604 For example, suppose an option always takes a Boolean value.  You can
1605 ensure that the value is in fact a valid Boolean like this:
1606
1607 [example {% snit::type dog {
1608     option -shots -default no -validatemethod BooleanOption
1609
1610     method BooleanOption {option value} {
1611         if {![string is boolean -strict $value]} {
1612             error "expected a boolean value, got \"$value\""
1613         }
1614     }
1615 }
1616 ::dog
1617 % dog fido
1618 % fido configure -shots yes
1619 % fido configure -shots NotABooleanValue
1620 expected a boolean value, got "NotABooleanValue"
1621 %
1622 }]
1623
1624 Note that the same [const -validatemethod] can be used to validate any number
1625 of boolean options.
1626
1627 [para]
1628
1629 Any method can be a [const -validatemethod] provided that it takes
1630 two arguments, the option name and the new option value.
1631
1632
1633 [section {TYPE VARIABLES}]
1634
1635 [subsection {What is a type variable?}]
1636
1637 A type variable is a private variable associated with a Snit type
1638 rather than with a particular instance of the type.  In C++ and Java,
1639 the term [term "static member variable"] is used for the same notion.
1640 Type variables can be scalars or arrays.
1641
1642
1643 [subsection {How is a scalar type variable defined?}]
1644
1645 Scalar type variables are defined in the type definition using the
1646 [cmd typevariable] statement.  You can simply name it, or you can
1647 initialize it with a value:
1648
1649 [para]
1650 [example {
1651 snit::type mytype {
1652     # Define variable "greeting" and initialize it with "Howdy!"
1653     typevariable greeting "Howdy!"
1654 }
1655 }]
1656 [para]
1657
1658 Every object of type [cmd mytype] now has access to a single variable
1659 called [var greeting].
1660
1661 [subsection {How is an array-valued type variable defined?}]
1662
1663 Array-valued type variables are also defined using the
1664 [cmd typevariable] command; to initialize them, include the 
1665 [const -array] option:
1666
1667 [para]
1668 [example {snit::type mytype {
1669     # Define typearray variable "greetings"
1670     typevariable greetings -array {
1671         formal "Good Evening"
1672         casual "Howdy!"
1673     }
1674 }
1675 }]
1676 [para]
1677
1678 [subsection {What happens if I don't initialize a type variable?}]
1679
1680 Variables do not really exist until they are given values.  If you 
1681 do not initialize a variable when you define it, then you must be
1682 sure to assign a value to it (in the type constructor, say)
1683 before you reference it.
1684
1685 [subsection {Are there any limitations on type variable names?}]
1686
1687 Type variable names have the same restrictions as 
1688 the names of [sectref {INSTANCE VARIABLES}] do.
1689
1690 [subsection {Do I need to declare my type variables in my methods?}]
1691
1692 No. Once you've defined a type variable in the type definition, it can
1693 be used in [sectref {INSTANCE METHODS}] or [sectref {TYPE METHODS}] without
1694 declaration.  This differs from normal Tcl practice, in which all
1695 non-local variables in a proc need to be declared.
1696
1697 [para]
1698
1699 Type variables are subject to the same speed/readability tradeoffs
1700 as instance variables; see
1701 [sectref {Do I need to declare my instance variables in my methods?}] 
1702
1703 [subsection {How do I pass a type variable's name to another object?}]
1704
1705 In Tk, it's common to pass a widget a variable name; for example, Tk
1706 label widgets have a [option -textvariable] option which names the
1707 variable which will contain the widget's text.  This allows the
1708 program to update the label's value just by assigning a new value to
1709 the variable.
1710
1711 [para]
1712
1713 If you naively pass a type variable name to the label widget, you'll
1714 be confused by the result; Tk will assume that the name names a global
1715 variable.  Instead, you need to provide a fully-qualified variable
1716 name.  From within an instance method or a constructor, you can fully
1717 qualify the type variable's name using the [cmd mytypevar] command:
1718
1719 [para] 
1720 [example {snit::widget mywidget {
1721     typevariable labeltext ""
1722
1723     constructor {args} {
1724         # ...
1725
1726         label $win.label -textvariable [mytypevar labeltext]
1727
1728         # ...
1729     }
1730 }
1731 }]
1732 [para]
1733
1734 [subsection {How do I make a type variable public?}]
1735
1736 There are two ways to do this.  The preferred way is to write a pair
1737 of [sectref {TYPE METHODS}] to set and query the type variable's value.
1738
1739 [para]
1740
1741 Type variables are stored in the type's namespace, which has
1742 the same name as the type itself.  Thus, you can also
1743 publicize the type variable's name in your
1744 documentation so that clients can access it directly.  For example,
1745
1746 [para]
1747 [example {snit::type mytype {
1748     typevariable myvariable
1749 }
1750
1751 set ::mytype::myvariable "New Value"
1752 }]
1753 [para]
1754
1755 [section {TYPE METHODS}]
1756
1757 [subsection {What is a type method?}]
1758
1759 A type method is a procedure associated with the type itself rather
1760 than with any specific instance of the type, and called as a
1761 subcommand of the type command.
1762
1763 [subsection {How do I define a type method?}]
1764
1765 Type methods are defined in the type definition using the
1766
1767 [cmd typemethod] statement:
1768
1769 [para]
1770 [example {snit::type dog {
1771     # List of pedigreed dogs
1772     typevariable pedigreed
1773
1774     typemethod pedigreedDogs {} {
1775         return $pedigreed
1776     }
1777 }
1778 }]
1779 [para]
1780
1781 Suppose the [cmd dog] type maintains a list of the names of the dogs
1782 that have pedigrees.  The [cmd pedigreedDogs] type method returns this
1783 list.
1784
1785 [para]
1786
1787 The [cmd typemethod] statement looks just like a normal Tcl
1788 [cmd proc], except that it appears in a [cmd snit::type] definition.
1789 Notice that every type method gets an implicit argument called
1790 [var type], which contains the fully-qualified type name.
1791
1792 [subsection {How does a client call a type method?}]
1793
1794 The type method name becomes a subcommand of the type's command.  For
1795 example, assuming that the constructor adds each pedigreed dog to the
1796 list of [var pedigreedDogs],
1797
1798 [para]
1799 [example {snit::type dog {
1800     option -pedigreed 0
1801
1802     # List of pedigreed dogs
1803     typevariable pedigreed
1804
1805     typemethod pedigreedDogs {} {
1806         return $pedigreed
1807     }
1808
1809     # ...
1810 }
1811
1812 dog spot -pedigreed 1
1813 dog fido
1814
1815 foreach dog [dog pedigreedDogs] { ... }
1816 }]
1817 [para]
1818
1819 [subsection {Are there any limitations on type method names?}]
1820
1821 Not really, so long as you avoid the standard type method names:
1822 [method create], [method destroy], and [method info].
1823
1824
1825 [subsection {How do I make a type method private?}]
1826
1827 It's sometimes useful to define private type methods, that is, type
1828 methods intended to be called only by other type or instance methods
1829 of the same object.
1830
1831 [para]
1832
1833 Snit doesn't implement any access control on type methods; by
1834 convention, the names of public methods begin with a lower-case
1835 letter, and the names of private methods begin with an upper-case
1836 letter.
1837
1838 [para]
1839
1840 Alternatively, a Snit [cmd proc] can be used as a private type method; see
1841 [sectref PROCS].
1842
1843
1844 [subsection {Are there any limitations on type method arguments?}]
1845
1846 Method argument lists are defined just like normal Tcl proc argument
1847 lists; in particular, they can include arguments with default values
1848 and the [var args] argument.
1849
1850 [para]
1851
1852 However, every type method is called with an implicit argument called
1853 [var type] that contains the name of the type command.  In addition,
1854 type methods should by convention avoid using the names of the
1855 arguments implicitly defined for [sectref {INSTANCE METHODS}].
1856
1857 [subsection {How does an instance or type method call a type method?}]
1858
1859 If an instance or type method needs to call a type method, it should
1860 use [var \$type] to do so:
1861
1862 [para]
1863 [example {snit::type dog {
1864
1865     typemethod pedigreedDogs {} { ... }
1866
1867     typemethod printPedigrees {} {
1868         foreach obj [$type pedigreedDogs] { ... }
1869     }
1870 }
1871 }]
1872 [para]
1873
1874 [subsection {How do I pass a type method as a callback?}]
1875
1876 It's common in Tcl to pass a snippet of code to another object, for it
1877 to call later.  Because types cannot be renamed, you can just
1878 use the type name, or, if the callback is registered from within
1879 a type method, [var type].  For example, suppose we want to print a
1880 list of pedigreed dogs when a Tk button is pushed:
1881
1882 [para]
1883 [example {
1884 button .btn -text "Pedigrees" -command [list dog printPedigrees]
1885 pack .btn
1886 }]
1887
1888 Alternatively, from a method or type method you can use the 
1889 [cmd mytypemethod] command, just as you would use [cmd mymethod]
1890 to define a callback command for [sectref {INSTANCE METHODS}].
1891
1892 [subsection {Can type methods be hierarchical?}]
1893
1894 Yes, you can define hierarchical type methods in just the same way as
1895 you can define hierarchical instance methods.  See
1896 [sectref {INSTANCE METHODS}] for more.
1897
1898 [section PROCS]
1899
1900 [subsection {What is a proc?}]
1901
1902 A Snit [cmd proc] is really just a Tcl proc defined within the type's
1903 namespace.  You can use procs for private code that isn't related to
1904 any particular instance. 
1905
1906 [subsection {How do I define a proc?}]
1907
1908 Procs are defined by including a [cmd proc] statement in the type
1909 definition:
1910
1911 [para]
1912 [example {snit::type mytype {
1913     # Pops and returns the first item from the list stored in the
1914     # listvar, updating the listvar
1915    proc pop {listvar} { ... }
1916
1917    # ...
1918 }
1919 }]
1920 [para]
1921
1922 [subsection {Are there any limitations on proc names?}]
1923
1924 Any name can be used, so long as it does not begin with [const Snit_];
1925 names beginning with [const Snit_] are reserved for Snit's own use.
1926 However, the wise programmer will avoid [cmd proc] names ([cmd set],
1927 [cmd list], [cmd if], etc.) that would shadow standard Tcl
1928 command names.
1929
1930 [para]
1931
1932 [cmd proc] names, being private, should begin with a capital letter according
1933 to convention; however, as there are typically no public [cmd proc]s
1934 in the type's namespace it doesn't matter much either way.
1935
1936 [subsection {How does a method call a proc?}]
1937
1938 Just like it calls any Tcl command.  For example,
1939
1940 [para]
1941
1942 [example {snit::type mytype {
1943     # Pops and returns the first item from the list stored in the
1944     # listvar, updating the listvar
1945     proc pop {listvar} { ... }
1946
1947     variable requestQueue {}
1948
1949     # Get one request from the queue and process it.
1950     method processRequest {} {
1951         set req [pop requestQueue]
1952     }
1953 }
1954 }]
1955 [para]
1956
1957 [subsection {How can I pass a proc to another object as a callback?}]
1958
1959 The [cmd myproc] command returns a callback command for the 
1960 [cmd proc], just as [cmd mymethod] does for a method.
1961
1962 [section {TYPE CONSTRUCTORS}]
1963
1964 [subsection {What is a type constructor?}]
1965
1966 A type constructor is a body of code that initializes the type as a
1967 whole, rather like a C++ static initializer.  The body of a type
1968 constructor is executed once when the type is defined, and never
1969 again.
1970
1971 [para]
1972
1973 A type can have at most one type constructor.
1974
1975
1976 [subsection {How do I define a type constructor?}]
1977
1978 A type constructor is defined by using the [cmd typeconstructor]
1979 statement in the type definition.  For example, suppose the type uses
1980 an array-valued type variable as a look-up table, and the values in
1981 the array have to be computed at start-up.
1982
1983 [para]
1984 [example {% snit::type mytype {
1985     typevariable lookupTable
1986
1987     typeconstructor {
1988         array set lookupTable {key value...}
1989     }
1990 }
1991 }]
1992 [para]
1993
1994
1995
1996 [section CONSTRUCTORS]
1997
1998 [subsection {What is a constructor?}]
1999
2000 In object-oriented programming, an object's constructor is responsible
2001 for initializing the object completely at creation time. The constructor
2002 receives the list of options passed to the [cmd snit::type] command's
2003 [method create] method and can then do whatever it likes.  That might include
2004 computing instance variable values, reading data from files, creating
2005 other objects, updating type and instance variables, and so forth.
2006
2007 [para]
2008
2009 The constructor's return value is ignored (unless it's an
2010 error, of course).
2011
2012
2013 [subsection {How do I define a constructor?}]
2014
2015 A constructor is defined by using the [cmd constructor] statement in
2016 the type definition.  Suppose that it's desired to keep a list of all
2017 pedigreed dogs.  The list can be maintained in a 
2018 type variable and retrieved by a type method.  Whenever a dog is
2019 created, it can add itself to the list--provided that it's registered
2020 with the American Kennel Club.
2021
2022 [para] 
2023 [example {% snit::type dog {
2024     option -akc 0
2025
2026     typevariable akcList {}
2027
2028     constructor {args} {
2029         $self configurelist $args
2030
2031         if {$options(-akc)} {
2032             lappend akcList $self
2033         }
2034     }
2035
2036     typemethod akclist {} {
2037         return $akcList
2038     }
2039 }
2040 ::dog
2041 % dog spot -akc 1
2042 ::spot
2043 % dog fido
2044 ::fido
2045 % dog akclist
2046 ::spot
2047 %
2048 }]
2049 [para]
2050
2051 [subsection {What does the default constructor do?}]
2052
2053 If you don't provide a constructor explicitly, you get the default
2054 constructor, which is identical to the explicitly-defined
2055 constructor shown here:
2056
2057 [para]
2058 [example {snit::type dog {
2059     constructor {args} {
2060         $self configurelist $args
2061     }
2062 }
2063 }]
2064 [para]
2065
2066 When the constructor is called, [var args] will be set to the list of
2067 arguments that follow the object's name.  The constructor is allowed
2068 to interpret this list any way it chooses; the normal convention is
2069 to assume that it's a list of option names and values, as shown in the
2070 example above.  If you simply want to save the option values, you
2071 should use the [method configurelist] method, as shown.
2072
2073 [subsection {Can I choose a different set of arguments for the constructor?}]
2074
2075 Yes, you can.  For example, suppose we wanted to be sure that the
2076 breed was explicitly stated for every dog at creation time, and
2077 couldn't be changed thereafter.  One way to do that is as follows:
2078
2079 [para]
2080 [example {% snit::type dog {
2081     variable breed
2082
2083     option -color brown
2084     option -akc 0
2085
2086     constructor {theBreed args} {
2087         set breed $theBreed
2088         $self configurelist $args
2089     }
2090
2091     method breed {} { return $breed }
2092 }
2093 ::dog
2094 % dog spot dalmatian -color spotted -akc 1
2095 ::spot
2096 % spot breed
2097 dalmatian
2098 }]
2099 [para]
2100
2101 The drawback is that this syntax is non-standard, and may
2102 limit the compatibility of your new type with other people's code.
2103 For example, Snit assumes that it can create 
2104 [sectref COMPONENTS] using the standard creation syntax.
2105
2106 [subsection {Are there any limitations on constructor arguments?}]
2107
2108 Constructor argument lists are subject to the same limitations
2109 as those on instance method argument lists.  It has the
2110 same implicit arguments, and can contain default values and the 
2111 [var args] argument.
2112
2113 [subsection "Is there anything special about writing the constructor?"]
2114
2115 Yes.  Writing the constructor can be tricky if you're delegating
2116 options to components, and there are specific issues relating to
2117 [cmd snit::widget]s and [cmd snit::widgetadaptor]s.  See 
2118 [sectref {DELEGATION}], [sectref {WIDGETS}], 
2119 [sectref {WIDGET ADAPTORS}], and [sectref {THE TK OPTION DATABASE}].
2120
2121 [section DESTRUCTORS]
2122
2123 [subsection {What is a destructor?}]
2124
2125 A destructor is a special kind of method that's called when an object
2126 is destroyed.  It's responsible for doing any necessary clean-up when
2127 the object goes away: destroying [sectref COMPONENTS], closing files,
2128 and so forth.
2129
2130 [subsection {How do I define a destructor?}]
2131
2132 Destructors are defined by using the [cmd destructor] statement in the
2133 type definition.
2134
2135 [para]
2136 Suppose we're maintaining a list of pedigreed dogs;
2137 then we'll want to remove dogs from it when they are destroyed.
2138
2139 [para]
2140 [example {snit::type dog {
2141     option -akc 0
2142
2143     typevariable akcList {}
2144
2145     constructor {args} {
2146         $self configurelist $args
2147
2148         if {$options(-akc)} {
2149             lappend akcList $self
2150         }
2151     }
2152
2153     destructor {
2154         set ndx [lsearch $akcList $self]
2155
2156         if {$ndx != -1} {
2157             set akcList [lreplace $akcList $ndx $ndx]
2158         }
2159     }
2160
2161     typemethod akclist {} {
2162         return $akcList
2163     }
2164 }
2165 }]
2166 [para]
2167
2168 [subsection {Are there any limitations on destructor arguments?}]
2169
2170 Yes; a destructor has no explicit arguments.
2171
2172 [subsection {What implicit arguments are passed to the destructor?}]
2173
2174 The destructor gets the same implicit arguments that are passed to
2175 [sectref {INSTANCE METHODS}]: [var type], [var selfns], [var win], and
2176 [var self].
2177
2178 [subsection {Must components be destroyed explicitly?}]
2179
2180 Yes and no.
2181
2182 [para]
2183
2184 Any Tk widgets created by a [cmd snit::widget] or
2185 [cmd snit::widgetadaptor] will be destroyed automatically by Tk
2186 when the megawidget is destroyed, in keeping with normal Tk behavior 
2187 (destroying a parent widget destroys the whole tree).
2188
2189 [para]
2190
2191 Components of normal [cmd snit::types], on the other hand, 
2192 are never destroyed automatically, nor are non-widget components 
2193 of Snit megawidgets.  If your object creates them in its 
2194 constructor, then it should generally destroy them in its destructor.
2195
2196 [subsection {Is there any special about writing a destructor?}]
2197
2198 Yes.  If an object's constructor throws an error, the object's
2199 destructor will be called to clean up; this means that the object
2200 might not be completely constructed when the destructor is called.
2201 This can cause the destructor to throw its own error; the result
2202 is usually misleading, confusing, and unhelpful.  Consequently, it's
2203 important to write your destructor so that it's fail-safe.  
2204
2205 [para]
2206
2207 For example, a [cmd dog] might create a [cmd tail] component; the
2208 component will need to be destroyed.  But suppose there's an error
2209 while processing the creation options--the destructor will be called,
2210 and there will be no [cmd tail] to destroy.  The simplest solution is
2211 generally to catch and ignore any errors while destroying components.
2212
2213 [example {snit::type dog {
2214     component tail
2215
2216     constructor {args} {
2217         $self configurelist $args
2218
2219         set tail [tail %AUTO%]
2220     }
2221
2222     destructor {
2223         catch {$tail destroy}
2224     }
2225 }
2226 }]
2227
2228
2229 [section COMPONENTS]
2230
2231 [subsection {What is a component?}]
2232
2233 Often an object will create and manage a number of other objects.  A
2234 Snit megawidget, for example, will often create a number of Tk
2235 widgets.  These objects are part of the main object; it is composed
2236 of them, so they are called components of the object.
2237
2238 [para]
2239
2240 But Snit also has a more precise meaning for 
2241 [sectref COMPONENTS COMPONENT].  The components of a Snit object are those
2242 objects to which methods or options can be delegated.
2243 (See [sectref DELEGATION] for more information about delegation.)
2244
2245 [subsection {How do I declare a component?}]
2246
2247 First, you must decide what role a component plays within your object,
2248 and give the role a name.  Then, you declare the component using its
2249 role name and the [cmd component] statement.  The [cmd component]
2250 statement declares an [term {instance variable}] which is used to
2251 store the component's command name when the component is created.
2252
2253 [para]
2254
2255 For example, suppose your [cmd dog] object
2256 creates a [cmd tail] object (the better to wag with, no doubt):
2257
2258 [para]
2259 [example {snit::type dog {
2260     component mytail
2261
2262     constructor {args} {
2263         # Create and save the component's command
2264         set mytail [tail %AUTO% -partof $self]
2265         $self configurelist $args
2266     }
2267
2268     method wag {} {
2269         $mytail wag
2270     }
2271 }
2272 }]
2273 [para]
2274
2275 As shown here, it doesn't matter what the [cmd tail] object's real
2276 name is; the [cmd dog] object refers to it by its component name.
2277
2278 [para]
2279
2280 The above example shows one way to delegate the [method wag] method to
2281 the [var mytail] component; see [sectref DELEGATION] for an easier way.
2282
2283 [subsection {How is a component named?}]
2284
2285 A component has two names.  The first name is that of the component
2286 variable; this represents the role the component object plays within
2287 the Snit object.  This is the component name proper, and is the name
2288 used to refer to the component within Snit code.  The second name is
2289 the name of the actual component object created by the Snit object's
2290 constructor.  This second name is always a Tcl command name, and is
2291 referred to as the component's object name.
2292
2293 [para]
2294
2295 In the example in the previous question, the component name is 
2296 [const mytail]; the [const mytail] component's object name is chosen
2297 automatically by Snit since [const %AUTO%] was used when the component
2298 object was created.
2299
2300 [subsection {Are there any limitations on component names?}]
2301
2302 Yes.  [cmd snit::widget] and [cmd snit::widgetadaptor] objects have a special
2303 component called the [var hull] component; thus, the name [var hull]
2304 should be used for no other purpose.
2305
2306 [para]
2307
2308 Otherwise, since component names are in fact instance variable names
2309 they must follow the rules for [sectref {INSTANCE VARIABLES}].
2310
2311 [subsection {What is an owned component?}]
2312
2313 An [term owned] component is a component whose object command's
2314 lifetime is controlled by the [cmd snit::type] or [cmd snit::widget].
2315
2316 [para]
2317
2318 As stated above, a component is an object to
2319 which our object can delegate methods or options.  Under this
2320 definition, our object will usually create its component objects,
2321 but not necessarily.  Consider the following: a dog object has a tail
2322 component; but tail knows that it's part of the dog:
2323
2324 [example {snit::type dog {
2325     component mytail
2326
2327     constructor {args} {
2328         set mytail [tail %AUTO% -partof $self]
2329         $self configurelist $args
2330     }
2331
2332     destructor {
2333         catch {$mytail destroy}
2334     }
2335
2336     delegate method wagtail to mytail as wag
2337
2338     method bark {} {
2339         return "$self barked."
2340     }
2341 }
2342
2343  snit::type tail {
2344      component mydog
2345      option -partof -readonly yes
2346
2347      constructor {args} {
2348          $self configurelist $args
2349          set mydog $options(-partof)
2350      }
2351
2352      method wag {} {
2353          return "Wag, wag."
2354      }
2355
2356      method pull {} {
2357          $mydog bark
2358      }
2359  }
2360 }]
2361
2362 Thus, if you ask a dog to wag its tail, it tells its tail to wag;
2363 and if you pull the dog's tail, the tail tells the dog to bark.  In
2364 this scenario, the tail is a component of the dog, and the dog is a
2365 component of the tail, but the dog owns the tail and not the other way
2366 around.
2367
2368 [subsection {What does the install command do?}]
2369
2370 The [cmd install] command creates an owned component using a specified
2371 command, and assigns the result to the component's instance variable.
2372 For example:
2373
2374 [example {snit::type dog {
2375     component mytail
2376
2377     constructor {args} {
2378         # set mytail [tail %AUTO% -partof $self]
2379         install mytail using tail %AUTO% -partof $self
2380         $self configurelist $args
2381     }
2382 }
2383 }]
2384
2385 In a [cmd snit::type]'s code, the [cmd install]
2386 command shown above is equivalent to the [const {set mytail}] command
2387 that's commented out.  In a [cmd snit::widget]'s or 
2388 [cmd snit::widgetadaptor]'s, code, however, the
2389 [cmd install] command also queries [sectref {THE TK OPTION DATABASE}]
2390 and initializes the new component's options accordingly.  For consistency,
2391 it's a good idea to get in the habit of using [cmd install] for all
2392 owned components.
2393
2394 [subsection {Must owned components be created in the constructor?}]
2395
2396 No, not necessarily.  In fact, there's no reason why an
2397 object can't destroy and recreate a component multiple times over
2398 its own lifetime.
2399
2400 [subsection {Are there any limitations on component object names?}]
2401
2402 Yes.
2403
2404 [para]
2405
2406 Component objects which are Tk widgets or megawidgets must have valid
2407 Tk window names.
2408
2409 [para]
2410
2411 Component objects which are not widgets or megawidgets must have
2412 fully-qualified command names, i.e., names which include the full
2413 namespace of the command.  Note that Snit always creates objects with
2414 fully qualified names.
2415
2416 [para]
2417
2418 Next, the object names of components and owned by your object 
2419 must be unique.  This is no problem for widget components, since
2420 widget names are always unique; but consider the following code:
2421
2422 [para]
2423 [example {snit::type tail { ... }
2424
2425 snit::type dog {
2426     delegate method wag to mytail
2427
2428     constructor {} {
2429         install mytail using tail mytail
2430     }
2431 }
2432 }]
2433 [para]
2434
2435 This code uses the component name, [const "mytail"], as the component object
2436 name.  This is not good, and here's why: Snit instance code executes
2437 in the Snit type's namespace.  In this case, the [const mytail] component is
2438 created in the [const ::dog::] namespace, and will thus have the name
2439 [cmd ::dog::mytail].
2440
2441 [para]
2442
2443 Now, suppose you create two dogs.  Both dogs will attempt to
2444 create a tail called [cmd ::dog::mytail].  The first will succeed,
2445 and the second will fail, since Snit won't let you create an object if
2446 its name is already a command.  Here are two ways to avoid this situation:
2447
2448 [para]
2449
2450 First, if the component type is a [cmd snit::type] you can
2451 specify [const %AUTO%] as its name, and be guaranteed to get a unique name.
2452 This is the safest thing to do:
2453
2454 [para]
2455 [example {
2456     install mytail using tail %AUTO%
2457 }]
2458 [para]
2459
2460 If the component type isn't a [cmd snit::type] you can create
2461 the component in the object's instance namespace:
2462
2463 [para]
2464 [example {
2465     install mytail using tail ${selfns}::mytail
2466 }]
2467 [para]
2468
2469 Make sure you pick a unique name within the instance namespace.
2470
2471 [subsection {Must I destroy the components I own?}]
2472
2473 That depends.  When a parent widget is destroyed, all child widgets
2474 are destroyed automatically. Thus, if your object is a [cmd snit::widget]
2475 or [cmd snit::widgetadaptor] you don't need to destroy any components
2476 that are widgets, because they will generally be children or
2477 descendants of your megawidget.
2478
2479 [para]
2480
2481 If your object is an instance of [cmd snit::type], though, none of its
2482 owned components will be destroyed automatically, nor will be
2483 non-widget components of a [cmd snit::widget] be destroyed
2484 automatically.  All such owned components must be destroyed
2485 explicitly, or they won't be destroyed at all.
2486
2487 [subsection {Can I expose a component's object command as part of my interface?}]
2488
2489 Yes, and there are two ways to do it.  The most appropriate way is
2490 usually to use [sectref DELEGATION].  Delegation allows you to pass
2491 the options and methods you specify along to particular components.
2492 This effectively hides the components from the users of your type, and
2493 ensures good encapsulation.
2494
2495 [para]
2496
2497 However, there are times when it's appropriate, not to mention
2498 simpler, just to make the entire component part of your type's public
2499 interface.
2500
2501
2502 [subsection {How do I expose a component's object command?}]
2503
2504 When you declare the component, specify the [cmd component]
2505 statement's [const -public] option.  The value of this option is the
2506 name of a method which will be delegated to your component's object 
2507 command.
2508
2509 [para]
2510
2511 For example, supposed you've written a combobox megawidget which owns
2512 a listbox widget, and you want to make the listbox's entire interface 
2513 public.  You can do it like this:
2514
2515 [para]
2516 [example {snit::widget combobox {
2517      component listbox -public listbox
2518
2519      constructor {args} {
2520          install listbox using listbox $win.listbox ....
2521      }
2522 }
2523
2524 combobox .mycombo
2525 .mycombo listbox configure -width 30
2526 }]
2527 [para]
2528
2529 Your comobox widget, [cmd .mycombo], now has a [method listbox] method
2530 which has all of the same subcommands as the listbox widget itself.
2531 Thus, the above code sets the listbox component's width to 30.
2532
2533 [para]
2534
2535 Usually you'll let the method name be the same as the component name;
2536 however, you can name it anything you like.
2537
2538 [section {TYPE COMPONENTS}]
2539
2540 [subsection {What is a type component?}]
2541
2542 A type component is a component that belongs to the type itself
2543 instead of to a particular instance of the type.  The relationship
2544 between components and type components is the same as the
2545 relationship between [sectref {INSTANCE VARIABLES}] and 
2546 [sectref {TYPE VARIABLES}].  Both [sectref {INSTANCE METHODS}] and
2547 [sectref {TYPE METHODS}] can be delegated to type components.
2548
2549 [para]
2550
2551 Once you understand [sectref COMPONENTS] and
2552 [sectref {DELEGATION}], type components are just more of the same.
2553
2554 [subsection {How do I declare a type component?}]
2555
2556 Declare a type component using the [cmd typecomponent] statement.  It
2557 takes the same options ([const -inherit] and [const -public]) as the
2558 [cmd component] statement does, and defines a type variable to hold
2559 the type component's object command.
2560
2561 [para]
2562
2563 Suppose in your model you've got many dogs, but only one
2564 veterinarian.  You might make the veterinarian a type component.
2565
2566 [example {snit::type veterinarian { ... }
2567
2568 snit::type dog {
2569     typecomponent vet
2570
2571     # ...
2572 }
2573 }]
2574
2575 [subsection {How do I install a type component?}]
2576
2577 Just use the [cmd set] command to assign the component's object
2578 command to the type component.  Because types 
2579 (even [cmd snit::widget] types) are not widgets, and do not have
2580 options anyway, the extra features of the [cmd install] command are
2581 not needed.
2582
2583 [para]
2584
2585 You'll usually install type components in the type constructor, as
2586 shown here:
2587
2588 [example {snit::type veterinarian { ... }
2589
2590 snit::type dog {
2591     typecomponent vet
2592
2593     typeconstructor {
2594         set vet [veterinarian %AUTO%]
2595     }
2596 }
2597 }]
2598
2599 [subsection {Are there any limitations on type component names?}]
2600
2601 Yes, the same as on [sectref {INSTANCE VARIABLES}], 
2602 [sectref {TYPE VARIABLES}], and normal [sectref COMPONENTS].
2603
2604
2605 [section DELEGATION]
2606
2607 [subsection {What is delegation?}]
2608
2609 Delegation, simply put, is when you pass a task you've been given to
2610 one of your assistants.  (You do have assistants, don't you?)  Snit
2611 objects can do the same thing.  The following example shows one way in
2612 which the [cmd dog] object can delegate its [cmd wag] method and its
2613 [option -taillength] option to its [cmd tail] component.
2614
2615 [para] 
2616 [example {snit::type dog {
2617     variable mytail
2618
2619     option -taillength -configuremethod SetTailOption -cgetmethod GetTailOption
2620     
2621
2622     method SetTailOption {option value} {
2623          $mytail configure $option $value
2624     }
2625
2626     method GetTailOption {option} {
2627          $mytail cget $option
2628     }
2629
2630     method wag {} {
2631         $mytail wag
2632     }
2633
2634     constructor {args} {
2635         install mytail using tail %AUTO% -partof $self
2636         $self configurelist $args
2637     }
2638
2639 }
2640 }]
2641 [para]
2642
2643 This is the hard way to do it, by it demonstrates what delegation is
2644 all about.  See the following answers for the easy way to do it.
2645
2646 [para]
2647
2648 Note that the constructor calls the [method configurelist] method
2649 [cmd after] it creates its [cmd tail]; otherwise,
2650 if [option -taillength] appeared in the list of [var args] we'd get an
2651 error.
2652
2653 [subsection {How can I delegate a method to a component object?}]
2654
2655 Delegation occurs frequently enough that Snit makes it easy. Any
2656 method can be delegated to any component or type component 
2657 by placing a single [cmd delegate] statement in the type definition.
2658
2659 (See [sectref COMPONENTS] and [sectref {TYPE COMPONENTS}]
2660 for more information about component names.)
2661
2662 [para]
2663
2664 For example, here's a much better way to delegate the [cmd dog]
2665 object's [cmd wag] method:
2666
2667 [para]
2668 [example {% snit::type dog {
2669     delegate method wag to mytail
2670
2671     constructor {} {
2672         install mytail using tail %AUTO%
2673     }
2674 }
2675 ::dog
2676 % snit::type tail {
2677     method wag {} { return "Wag, wag, wag."}
2678 }
2679 ::tail
2680 % dog spot
2681 ::spot
2682 % spot wag
2683 Wag, wag, wag.
2684 }]
2685 [para]
2686
2687 This code has the same effect as the code shown under the previous
2688 question: when a [cmd dog]'s [cmd wag] method is called, the call and
2689 its arguments are passed along automatically to the [cmd tail] object.
2690
2691 [para]
2692
2693 Note that when a component is mentioned in a [cmd delegate] statement,
2694 the component's instance variable is defined implicitly.  However,
2695 it's still good practice to declare it explicitly using the
2696 [cmd component] statement.
2697
2698 [para]
2699
2700 Note also that you can define a method name using the [cmd method]
2701 statement, or you can define it using [cmd delegate]; you can't do
2702 both.
2703
2704 [subsection {Can I delegate to a method with a different name?}]
2705
2706 Suppose you wanted to delegate the [cmd dog]'s [method wagtail] method to
2707 the [cmd tail]'s [method wag] method.  After all you wag the tail, not
2708 the dog.  It's easily done:
2709
2710 [para]
2711 [example {snit::type dog {
2712     delegate method wagtail to mytail as wag
2713
2714     constructor {args} {
2715         install mytail using tail %AUTO% -partof $self
2716         $self configurelist $args
2717     }
2718 }
2719 }]
2720 [para]
2721
2722
2723 [subsection {Can I delegate to a method with additional arguments?}]
2724
2725 Suppose the [cmd tail]'s [method wag] method takes as an argument the
2726 number of times the tail should be wagged.  You want to delegate the
2727 [cmd dog]'s [method wagtail] method to the [cmd tail]'s [method wag]
2728 method, specifying that the tail should be wagged exactly three times.
2729 This is easily done, too:
2730
2731 [para]
2732 [example {snit::type dog {
2733     delegate method wagtail to mytail as {wag 3}
2734     # ...
2735 }
2736
2737 snit::type tail {
2738     method wag {count} {
2739         return [string repeat "Wag " $count]
2740     }
2741     # ...
2742 }
2743 }]
2744 [para]
2745
2746 [subsection {Can I delegate a method to something other than an object?}]
2747
2748 Normal method delegation assumes that you're delegating a method (a
2749 subcommand of an object command) to a method of another object (a 
2750 subcommand of a different object command).  But not all Tcl objects
2751 follow Tk conventions, and not everything you'd to which you'd like
2752 to delegate a method is necessary an object.  Consequently, Snit makes
2753 it easy to delegate a method to pretty much anything you like using
2754 the [cmd delegate] statement's [const using] clause.
2755
2756 [para]
2757
2758 Suppose your dog simulation stores dogs in a database, each dog as a
2759 single record.  The database API you're using provides a number of
2760 commands to manage records; each takes the record ID (a string you
2761 choose) as its first argument.  For example, [cmd saverec]
2762 saves a record.  If you let the record ID be the name of the dog
2763 object, you can delegate the dog's [method save] method to the 
2764 [cmd saverec] command as follows:
2765
2766 [example {snit::type dog {
2767     delegate method save using {saverec %s}
2768 }
2769 }]
2770
2771 The [const %s] is replaced with the instance name when the 
2772 [method save] method is called; any additional arguments are the
2773 appended to the resulting command.
2774
2775 [para]
2776
2777 The [const using] clause understands a number of other %-conversions;
2778 in addition to the instance name, you can substitute in the method 
2779 name ([const %m]), the type name ([const %t]), the instance 
2780 namespace ([const %n]), the Tk window name ([const %w]), and,
2781 if a component or typecomponent name was given in the 
2782 [cmd delegate] statement, the component's object command 
2783 ([const %c]).
2784
2785 [subsection {How can I delegate a method to a type component object?}]
2786
2787 Just exactly as you would to a component object.  The 
2788 [cmd {delegate method}] statement accepts both component and type
2789 component names in its [const to] clause.
2790
2791 [subsection {How can I delegate a type method to a type component object?}]
2792
2793 Use the [cmd {delegate typemethod}] statement.  It works like
2794 [cmd {delegate method}], with these differences: first, it defines
2795 a type method instead of an instance method; second, the 
2796 [const using] clause ignores the [const {%s}], [const {%n}], 
2797 and [const {%w}] %-conversions.
2798
2799 [para]
2800
2801 Naturally, you can't delegate a type method to an instance
2802 component...Snit wouldn't know which instance should receive it.
2803
2804 [subsection {How can I delegate an option to a component object?}]
2805
2806 The first question in this section (see [sectref DELEGATION]) shows
2807 one way to delegate an option to a component; but this pattern occurs
2808 often enough that Snit makes it easy.  For example, every [cmd tail]
2809 object has a [option -length] option; we want to allow the creator of
2810 a [cmd dog] object to set the tail's length.  We can do this:
2811
2812 [para]
2813 [example {% snit::type dog {
2814     delegate option -length to mytail
2815
2816     constructor {args} {
2817         install mytail using tail %AUTO% -partof $self
2818         $self configurelist $args
2819     }
2820 }
2821 ::dog
2822 % snit::type tail {
2823     option -partof
2824     option -length 5
2825 }
2826 ::tail
2827 % dog spot -length 7
2828 ::spot
2829 % spot cget -length
2830 7
2831 }]
2832 [para]
2833
2834 This produces nearly the same result as the [const -configuremethod] and
2835 [const -cgetmethod] shown under the first question in this
2836 section: whenever a [cmd dog] object's [option -length] option is set
2837 or retrieved, the underlying [cmd tail] object's option is set or
2838 retrieved in turn.
2839
2840 [para]
2841
2842 Note that you can define an option name using the [cmd option]
2843 statement, or you can define it using [cmd delegate]; you can't do
2844 both.
2845
2846 [subsection {Can I delegate to an option with a different name?}]
2847
2848 In the previous answer we delegated the [cmd dog]'s [option -length]
2849 option down to its [cmd tail].  This is, of course, wrong.  The dog
2850 has a length, and the tail has a length, and they are different.  What
2851 we'd really like to do is give the [cmd dog] a [option -taillength]
2852 option, but delegate it to the [cmd tail]'s [option -length] option:
2853
2854 [para]
2855 [example {snit::type dog {
2856     delegate option -taillength to mytail as -length
2857
2858     constructor {args} {
2859         set mytail [tail %AUTO% -partof $self]
2860         $self configurelist $args
2861     }
2862 }
2863 }]
2864 [para]
2865
2866 [subsection {How can I delegate any unrecognized method or option to a component object?}]
2867
2868 It may happen that a Snit object gets most of its behavior from one of
2869 its components.  This often happens with [cmd snit::widgetadaptors],
2870 for example, where we wish to slightly the modify the behavior of an
2871 existing widget.  To carry on with our [cmd dog] example, however, suppose
2872 that we have a [cmd snit::type] called [cmd animal] that implements a
2873 variety of animal behaviors--moving, eating, sleeping, and so forth.
2874
2875 We want our [cmd dog] objects to inherit these same behaviors, while
2876 adding dog-like behaviors of its own.
2877
2878 Here's how we can give a [cmd dog] methods and options of its own
2879 while delegating all other methods and options to its [cmd animal]
2880 component:
2881
2882 [para]
2883 [example {snit::type dog {
2884     delegate option * to animal
2885     delegate method * to animal
2886
2887     option -akc 0
2888
2889     constructor {args} {
2890         install animal using animal %AUTO% -name $self
2891         $self configurelist $args
2892     }
2893
2894     method wag {} {
2895         return "$self wags its tail"
2896     }
2897 }
2898 }]
2899 [para]
2900
2901 That's it.  A [cmd dog] is now an [cmd animal] that has a
2902 [option -akc] option and can [cmd wag] its tail.
2903
2904 [para]
2905
2906 Note that we don't need to specify the full list of method names or
2907 option names that [cmd animal] will receive.
2908 It gets anything [cmd dog] doesn't recognize--and if it doesn't
2909 recognize it either, it will simply throw an error, just as it should.
2910
2911 [para]
2912
2913 You can also delegate all unknown type methods to a type component
2914 using [cmd {delegate typemethod *}].
2915
2916 [subsection {How can I delegate all but certain methods or options to a component?}]
2917
2918 In the previous answer, we said that every [cmd dog] is
2919 an [cmd animal] by delegating all unknown methods and options to the
2920 [var animal] component. But what if the [cmd animal] type has some
2921 methods or options that we'd like to suppress?
2922
2923 [para]
2924
2925 One solution is to explicitly delegate all the options and methods,
2926 and forgo the convenience of [cmd {delegate method *}] and
2927 [cmd {delegate option *}].  But if we wish to suppress only a few
2928 options or methods, there's an easier way:
2929
2930 [para]
2931 [example {snit::type dog {
2932     delegate option * to animal except -numlegs
2933     delegate method * to animal except {fly climb}
2934
2935     # ...
2936
2937     constructor {args} {
2938         install animal using animal %AUTO% -name $self -numlegs 4
2939         $self configurelist $args
2940     }
2941
2942     # ...
2943 }
2944 }]
2945 [para]
2946
2947 Dogs have four legs, so we specify that explicitly when we create the
2948 [var animal] component, and explicitly exclude [option -numlegs] from the
2949 set of delegated options.  Similarly, dogs can neither 
2950 [method fly] nor [method climb],
2951 so we exclude those [cmd animal] methods as shown.
2952
2953 [subsection {Can a hierarchical method be delegated?}]
2954
2955 Yes; just specify multiple words in the delegated method's name:
2956
2957 [para]
2958 [example {snit::type tail {
2959     method wag {} {return "Wag, wag"}
2960     method droop {} {return "Droop, droop"}
2961 }
2962
2963
2964 snit::type dog {
2965     delegate method {tail wag} to mytail
2966     delegate method {tail droop} to mytail
2967
2968     # ...
2969
2970     constructor {args} {
2971         install mytail using tail %AUTO%
2972         $self configurelist $args
2973     }
2974
2975     # ...
2976 }
2977 }]
2978 [para]
2979
2980 Unrecognized hierarchical methods can also be delegated; the following
2981 code delegates all subcommands of the "tail" method to the "mytail"
2982 component:
2983
2984 [para]
2985 [example {snit::type dog {
2986     delegate method {tail *} to mytail
2987
2988     # ...
2989 }
2990 }]
2991 [para]
2992
2993
2994
2995
2996 [section WIDGETS]
2997
2998 [subsection {What is a snit::widget?}]
2999
3000 A [cmd snit::widget] is the Snit version of what Tcl programmers
3001 usually call a [term megawidget]: a widget-like object usually
3002 consisting of one or more Tk widgets all contained within a Tk frame.
3003
3004 [para]
3005
3006 A [cmd snit::widget] is also a special kind of [cmd snit::type].  Just
3007 about everything in this FAQ list that relates to [cmd snit::types]
3008 also applies to [cmd snit::widgets].
3009
3010
3011 [subsection {How do I define a snit::widget?}]
3012
3013 [cmd snit::widgets] are defined using the [cmd snit::widget] command,
3014 just as [cmd snit::types] are defined by the [cmd snit::type] command.
3015
3016 [para]
3017
3018 The body of the definition can contain all of the same kinds of
3019 statements, plus a couple of others which will be mentioned below.
3020
3021
3022 [subsection {How do snit::widgets differ from snit::types?}]
3023
3024 [list_begin itemized]
3025 [item]
3026
3027 The name of an instance of a [cmd snit::type] can be any valid Tcl
3028 command name, in any namespace.
3029
3030 The name of an instance of a [cmd snit::widget] must be a valid Tk
3031 widget name, and its parent widget must already exist.
3032
3033
3034 [item]
3035
3036 An instance of a [cmd snit::type] can be destroyed by calling
3037
3038 its [cmd destroy] method.  Instances of a [cmd snit::widget] have no
3039 destroy method; use the Tk [cmd destroy] command instead.
3040
3041
3042 [item]
3043
3044 Every instance of a [cmd snit::widget] has one predefined component
3045 called its [var hull] component.
3046
3047 The hull is usually a Tk [cmd frame] or [cmd toplevel] widget; any other
3048 widgets created as part of the [cmd snit::widget] will usually be
3049 contained within the hull.
3050
3051 [item]
3052
3053 [cmd snit::widget]s can have their options receive default values from
3054 [sectref {THE TK OPTION DATABASE}].
3055
3056 [list_end]
3057
3058 [subsection {What is a hull component?}]
3059
3060 Snit can't create a Tk widget object; only Tk can do that.
3061
3062 Thus, every instance of a [cmd snit::widget] must be wrapped around a
3063 genuine Tk widget; this Tk widget is called the [term {hull component}].
3064
3065 Snit effectively piggybacks the behavior you define (methods, options,
3066 and so forth) on top of the hull component so that the whole thing
3067 behaves like a standard Tk widget.
3068
3069 [para]
3070
3071 For [cmd snit::widget]s the hull component must be a Tk widget that
3072 defines the [const -class] option.
3073
3074 [para]
3075
3076 [cmd snit::widgetadaptor]s differ from [cmd snit::widget]s chiefly in
3077 that any kind of widget can be used as the hull component; see
3078 [sectref {WIDGET ADAPTORS}].
3079
3080 [subsection {How can I set the hull type for a snit::widget?}]
3081
3082 A [cmd snit::widget]'s hull component will usually be a Tk [cmd frame]
3083 widget; however, it may be any Tk widget that defines the 
3084 [const -class] option.  You can
3085 explicitly choose the hull type you prefer by including the [cmd hulltype]
3086 command in the widget definition:
3087
3088 [para]
3089 [example {snit::widget mytoplevel {
3090     hulltype toplevel
3091
3092     # ...
3093 }
3094 }]
3095 [para]
3096
3097 If no [cmd hulltype] command appears, the hull will be a [cmd frame].
3098
3099 [para]
3100
3101 By default, Snit recognizes the following hull types: the Tk widgets
3102 [cmd frame], [cmd labelframe], [cmd toplevel], and the Tile widgets
3103 [cmd ttk::frame], [cmd ttk::labelframe], and [cmd ttk::toplevel].  To
3104 enable the use of some other kind of widget as the hull type, you can
3105 [cmd lappend] the widget command to the variable [var snit::hulltypes] (always
3106 provided the widget defines the [const -class] option.  For example,
3107 suppose Tk gets a new widget type called a [cmd prettyframe]:
3108
3109 [para]
3110 [example {lappend snit::hulltypes prettyframe
3111
3112 snit::widget mywidget {
3113     hulltype prettyframe
3114
3115     # ...
3116 }
3117 }]
3118 [para]
3119
3120
3121
3122 [subsection {How should I name widgets which are components of a snit::widget?}]
3123
3124 Every widget, whether a genuine Tk widget or a Snit megawidget, has to
3125 have a valid Tk window name.  When a [cmd snit::widget] is first
3126 created, its instance name, [var self], is a Tk window name;
3127
3128 however, if the [cmd snit::widget] is used as the hull component by a
3129 [cmd snit::widgetadaptor] its instance name will be changed to
3130 something else.  For this reason, every [cmd snit::widget] method,
3131 constructor, destructor, and so forth is passed another implicit
3132 argument, [var win], which is the window name of the megawidget.  Any
3133 children should be named using [var win] as the root.
3134
3135 [para]
3136
3137 Thus, suppose you're writing a toolbar widget, a frame consisting of a
3138 number of buttons placed side-by-side.  It might look something like
3139 this:
3140
3141 [para]
3142 [example {snit::widget toolbar {
3143     delegate option * to hull
3144
3145     constructor {args} {
3146         button $win.open -text Open -command [mymethod open]
3147         button $win.save -text Save -command [mymethod save]
3148
3149         # ....
3150
3151         $self configurelist $args
3152
3153     }
3154 }
3155 }]
3156 [para]
3157
3158 See also the question on renaming objects, toward the top of this
3159 file.
3160
3161 [section {WIDGET ADAPTORS}]
3162
3163 [subsection {What is a snit::widgetadaptor?}]
3164
3165 A [cmd snit::widgetadaptor] is a kind of [cmd snit::widget].  Whereas
3166 a [cmd snit::widget]'s hull is automatically created and is always a
3167 Tk frame, a [cmd snit::widgetadaptor] can be based on any Tk
3168 widget--or on any Snit megawidget, or even (with luck) on megawidgets
3169 defined using some other package.
3170
3171 [para]
3172
3173 It's called a [term {widget adaptor}] because it allows you to take an
3174 existing widget and customize its behavior.
3175
3176
3177 [subsection {How do I define a snit::widgetadaptor?}]
3178
3179 Use the [cmd snit::widgetadaptor] command.  The definition for a
3180 [cmd snit::widgetadaptor] looks just like that for a [cmd snit::type]
3181 or [cmd snit::widget], except that the constructor must create and
3182 install the hull component.
3183
3184 [para]
3185
3186 For example, the following code creates a read-only text widget by the
3187 simple device of turning its [method insert] and [method delete]
3188 methods into no-ops.  Then, we define new methods, [method ins] and
3189 [method del],
3190
3191 which get delegated to the hull component as [method insert] and
3192 [method delete].  Thus, we've adapted the text widget and given it new
3193 behavior while still leaving it fundamentally a text widget.
3194
3195 [para]
3196 [example {::snit::widgetadaptor rotext {
3197
3198     constructor {args} {
3199         # Create the text widget; turn off its insert cursor
3200         installhull using text -insertwidth 0
3201
3202         # Apply any options passed at creation time.
3203         $self configurelist $args
3204     }
3205
3206     # Disable the text widget's insert and delete methods, to
3207     # make this readonly.
3208     method insert {args} {}
3209     method delete {args} {}
3210
3211     # Enable ins and del as synonyms, so the program can insert and
3212     # delete.
3213     delegate method ins to hull as insert
3214     delegate method del to hull as delete
3215     
3216     # Pass all other methods and options to the real text widget, so
3217     # that the remaining behavior is as expected.
3218     delegate method * to hull
3219     delegate option * to hull
3220 }
3221 }]
3222 [para]
3223
3224 The most important part is in the constructor.
3225 Whereas [cmd snit::widget] creates the hull for you,
3226 [cmd snit::widgetadaptor] cannot -- it doesn't know what kind of
3227 widget you want.  So the first thing the constructor does is create
3228 the hull component (a Tk text widget in this case), and then installs
3229 it using the [cmd installhull] command.
3230
3231 [para]
3232
3233 [emph Note:] There is no instance command until you create one by
3234 installing a hull component.  Any attempt to pass methods to [var \$self]
3235 prior to calling [cmd installhull] will fail.
3236
3237 [subsection {Can I adapt a widget created elsewhere in the program?}]
3238
3239 Yes.
3240
3241 [para]
3242
3243 At times, it can be convenient to adapt a pre-existing widget instead
3244 of creating your own.
3245 For example, the Bwidget [cmd PagesManager] widget manages a
3246 set of [cmd frame] widgets, only one of which is visible at a time.
3247 The application chooses which [cmd frame] is visible.  All of the
3248 These [cmd frame]s are created by the [cmd PagesManager] itself, using
3249 its [method add] method.  It's convenient to adapt these frames to
3250 do what we'd like them to do.
3251
3252 [para]
3253
3254 In a case like this, the Tk widget will already exist when the
3255 [cmd snit::widgetadaptor] is created.  Snit provides an alternate form
3256 of the [cmd installhull] command for this purpose:
3257
3258 [para]
3259 [example {snit::widgetadaptor pageadaptor {
3260     constructor {args} {
3261         # The widget already exists; just install it.
3262         installhull $win
3263
3264         # ...
3265     }
3266 }
3267 }]
3268
3269 [subsection {Can I adapt another megawidget?}]
3270
3271 Maybe. If the other megawidget is a [cmd snit::widget] or
3272 [cmd snit::widgetadaptor], then yes.  If it isn't then, again, maybe.
3273 You'll have to try it and see.  You're most likely to have trouble
3274 with widget destruction--you have to make sure that your 
3275 megawidget code receives the [const <Destroy>] event before the
3276 megawidget you're adapting does.
3277
3278 [section {THE TK OPTION DATABASE}]
3279
3280 [subsection {What is the Tk option database?}]
3281
3282 The Tk option database is a database of default option values
3283 maintained by Tk itself; every Tk application has one.  The concept of
3284 the option database derives from something called the X Windows
3285 resource database; however, the option database is available in every
3286 Tk implementation, including those which do not use the X Windows
3287 system (e.g., Microsoft Windows).
3288
3289 [para]
3290
3291 Full details about the Tk option database are beyond the scope of this
3292 document; both [emph {Practical Programming in Tcl and Tk}] by Welch,
3293 Jones, and Hobbs, and [emph {Effective Tcl/Tk Programming}] by
3294 Harrison and McClennan., have good introductions to it.
3295
3296 [para]
3297
3298 Snit is implemented so that most of the time it will simply do the
3299 right thing with respect to the option database, provided that the
3300 widget developer does the right thing by Snit.  The body of this
3301 section goes into great deal about what Snit requires.  The following
3302 is a brief statement of the requirements, for reference.
3303
3304 [para]
3305
3306 [list_begin itemized]
3307
3308 [item]
3309
3310 If the widget's default widget class is not what is desired, set it
3311 explicitly using the [cmd widgetclass] statement in the widget
3312 definition.
3313
3314 [item]
3315
3316 When defining or delegating options, specify the resource and class
3317 names explicitly when necessary.
3318
3319 [item]
3320
3321 Use the [cmd {installhull using}] command to create and install the
3322 hull for [cmd snit::widgetadaptor]s.
3323
3324 [item]
3325
3326 Use the [cmd install] command to create and install all
3327 components which are widgets.
3328
3329 [item]
3330
3331 Use the [cmd install] command to create and install 
3332 components which aren't widgets if you'd like them to 
3333 receive option values from the option database.
3334
3335 [list_end]
3336 [para]
3337
3338 The interaction of Tk widgets with the option database is a complex
3339 thing; the interaction of Snit with the option database is even more
3340 so, and repays attention to detail.
3341
3342
3343 [subsection {Do snit::types use the Tk option database?}]
3344
3345 No, they don't; querying the option database requires a Tk window
3346 name, and [cmd snit::type]s don't have one.
3347
3348 [para]
3349
3350 If you create an instance of a [cmd snit::type] as a
3351 component of a [cmd snit::widget] or [cmd snit::widgetadaptor], on the
3352 other hand, and if any options are delegated to the component,
3353 and if you use [cmd install] to create and install it, then
3354 the megawidget will query the option database on the
3355 [cmd snit::type]'s behalf.  This might or might not be what you
3356 want, so take care.
3357
3358 [subsection {What is my snit::widget's widget class?}]
3359
3360 Every Tk widget has a "widget class": a name that is used when adding
3361 option settings to the database.  For Tk widgets, the widget class is
3362 the same as the widget command name with an initial capital.  For
3363 example, the widget class of the Tk [cmd button] widget is 
3364 [const Button].
3365
3366 [para]
3367
3368 Similarly, the widget class of a [cmd snit::widget] defaults to the
3369 unqualified type name with the first letter capitalized.  For example,
3370 the widget class of
3371
3372 [para]
3373 [example {snit::widget ::mylibrary::scrolledText { ... }
3374 }]
3375 [para]
3376
3377 is [const ScrolledText].
3378
3379 [para]
3380
3381 The widget class can also be set explicitly using the
3382 [cmd widgetclass] statement within the [cmd snit::widget] definition:
3383
3384 [para]
3385 [example {snit::widget ::mylibrary::scrolledText {
3386     widgetclass Text
3387
3388     # ...
3389 }
3390 }]
3391 [para]
3392
3393 The above definition says that a [cmd scrolledText] megawidget has the
3394 same widget class as an ordinary [cmd text] widget.  This might or
3395 might not be a good idea, depending on how the rest of the megawidget
3396 is defined, and how its options are delegated.
3397
3398 [subsection {What is my snit::widgetadaptor's widget class?}]
3399
3400 The widget class of a [cmd snit::widgetadaptor] is just the widget
3401 class of its hull widget; Snit has no control over this.
3402
3403 [para]
3404
3405 Note that the widget class can be changed only for [cmd frame] and
3406 [cmd toplevel] widgets, which is why these are the valid hull types
3407 for [cmd snit::widget]s.
3408
3409 [para]
3410
3411 Try to use [cmd snit::widgetadaptor]s only to make small modifications
3412 to another widget's behavior.  Then, it will usually not make sense to
3413 change the widget's widget class anyway.
3414
3415
3416 [subsection {What are option resource and class names?}]
3417
3418 Every Tk widget option has three names: the option name, the resource
3419 name, and the class name.
3420
3421 The option name begins with a hyphen and is all lowercase; it's used
3422 when creating widgets, and with the [cmd configure] and [cmd cget]
3423 commands.
3424
3425 [para]
3426
3427 The resource and class names are used to initialize option
3428 default values by querying the option database.
3429 The resource name is usually just the option
3430 name minus the hyphen, but may contain uppercase letters at word
3431 boundaries; the class name is usually just the resource
3432 name with an initial capital, but not always.  For example, here are
3433 the option, resource, and class names for several Tk [cmd text]
3434 widget options:
3435
3436 [para]
3437 [example {    -background         background         Background 
3438     -borderwidth        borderWidth        BorderWidth 
3439     -insertborderwidth  insertBorderWidth  BorderWidth 
3440     -padx               padX               Pad 
3441 }]
3442 [para]
3443
3444 As is easily seen, sometimes the resource and class names can be
3445 inferred from the option name, but not always.
3446
3447
3448 [subsection {What are the resource and class names for my megawidget's options?}]
3449
3450 For options implicitly delegated to a component using
3451 [cmd {delegate option *}], the resource and class names will be
3452 exactly those defined by the component.  The [cmd configure] method
3453 returns these names, along with the option's default and current
3454 values:
3455
3456 [para]
3457 [example {% snit::widget mytext {
3458     delegate option * to text
3459
3460     constructor {args} {
3461         install text using text .text
3462         # ...
3463     }
3464
3465     # ...
3466 }
3467 ::mytext
3468 % mytext .text
3469 .text
3470 % .text configure -padx
3471 -padx padX Pad 1 1
3472 %
3473 }]
3474 [para]
3475
3476 For all other options (whether locally defined or explicitly
3477 delegated), the resource and class names can be defined explicitly, or
3478 they can be allowed to have default values.
3479
3480 [para]
3481
3482 By default, the resource name is just the option name minus the
3483 hyphen; the the class name is just the option name with an initial
3484 capital letter.  For example, suppose we explicitly delegate "-padx":
3485
3486 [para]
3487 [example {% snit::widget mytext {
3488     option -myvalue 5
3489
3490     delegate option -padx to text
3491     delegate option * to text
3492
3493     constructor {args} {
3494         install text using text .text
3495         # ...
3496     }
3497
3498     # ...
3499 }
3500 ::mytext
3501 % mytext .text
3502 .text
3503 % .text configure -myvalue
3504 -myvalue myvalue Myvalue 5 5
3505 % .text configure -padx
3506 -padx padx Padx 1 1
3507 %
3508 }]
3509 [para]
3510
3511 Here the resource and class names are chosen using the default rules.
3512 Often these rules are sufficient, but in the case of "-padx" we'd most
3513 likely prefer that the option's resource and class names are the same
3514 as for the built-in Tk widgets.  This is easily done:
3515
3516 [para]
3517 [example {% snit::widget mytext {
3518     delegate option {-padx padX Pad} to text
3519
3520     # ...
3521 }
3522 ::mytext
3523 % mytext .text
3524 .text
3525 % .text configure -padx
3526 -padx padX Pad 1 1
3527 %
3528 }]
3529
3530
3531 [subsection {How does Snit initialize my megawidget's locally-defined options?}]
3532
3533 The option database is queried for each of the megawidget's
3534 locally-defined options, using the option's resource and class name.
3535 If the result isn't "", then it replaces the default value given in
3536 widget definition.  In either case, the default can be overridden by
3537 the caller.  For example,
3538
3539 [para]
3540 [example {option add *Mywidget.texture pebbled
3541
3542 snit::widget mywidget {
3543     option -texture smooth
3544     # ...
3545 }
3546
3547 mywidget .mywidget -texture greasy
3548 }]
3549 [para]
3550
3551 Here, [const -texture] would normally default to "smooth", but because of
3552 the entry added to the option database it defaults to "pebbled".
3553 However, the caller has explicitly overridden the default, and so the
3554 new widget will be "greasy".
3555
3556 [subsection {How does Snit initialize delegated options?}]
3557
3558 That depends on whether the options are delegated to the hull, or to
3559 some other component.
3560
3561
3562 [subsection {How does Snit initialize options delegated to the hull?}]
3563
3564 A [cmd snit::widget]'s hull is a widget, and given that its class has
3565 been set it is expected to query the option database for itself.  The
3566 only exception concerns options that are delegated to it with a
3567 different name.  Consider the following code:
3568
3569 [para]
3570 [example {option add *Mywidget.borderWidth 5
3571 option add *Mywidget.relief sunken
3572 option add *Mywidget.hullbackground red
3573 option add *Mywidget.background green
3574
3575 snit::widget mywidget {
3576     delegate option -borderwidth to hull
3577     delegate option -hullbackground to hull as -background
3578     delegate option * to hull
3579     # ...
3580 }
3581
3582 mywidget .mywidget
3583
3584 set A [.mywidget cget -relief]
3585 set B [.mywidget cget -hullbackground]
3586 set C [.mywidget cget -background]
3587 set D [.mywidget cget -borderwidth]
3588 }]
3589 [para]
3590
3591 The question is, what are the values of variables A, B, C and D?
3592
3593 [para]
3594
3595 The value of A is "sunken".  The hull is a Tk frame which has been
3596 given the widget class [const Mywidget]; it will automatically query the
3597 option database and pick up this value.  Since the [const -relief] option is
3598 implicitly delegated to the hull, Snit takes no action.
3599
3600 [para]
3601
3602 The value of B is "red".  The hull will automatically pick up the
3603 value "green" for its [const -background] option, just as it picked up the
3604 [const -relief] value.  However, Snit knows that [const -hullbackground]
3605 is mapped to the hull's [const -background] option; hence, it queries 
3606 the option database for [const -hullbackground] and gets "red" and 
3607 updates the hull accordingly.
3608
3609 [para]
3610
3611 The value of C is also "red", because [const -background] is implicitly
3612 delegated to the hull; thus, retrieving it is the same as retrieving
3613 [const -hullbackground].  Note that this case is unusual; the 
3614 [const -background] option should probably have been excluded using the delegate
3615 statement's [const except] clause, or (more likely) delegated to some other
3616 component.
3617
3618 [para]
3619
3620 The value of D is "5", but not for the reason you think.  Note that as
3621 it is defined above, the resource name for [const -borderwidth] defaults to
3622 [const borderwidth], whereas the option database entry is 
3623 [const borderWidth], in
3624 accordance with the standard Tk naming for this option.  As with
3625 [const -relief], the hull picks up its own [const -borderwidth]
3626 option before Snit
3627 does anything.  Because the option is delegated under its own name,
3628 Snit assumes that the correct thing has happened, and doesn't worry
3629 about it any further.  To avoid confusion, the 
3630 [const -borderwidth] option
3631 should have been delegated like this:
3632
3633 [para]
3634 [example {    delegate option {-borderwidth borderWidth BorderWidth} to hull
3635 }]
3636 [para]
3637
3638 For [cmd snit::widgetadaptor]s, the case is somewhat altered.  Widget
3639 adaptors retain the widget class of their hull, and the hull is not
3640 created automatically by Snit.  Instead, the [cmd snit::widgetadaptor]
3641 must call [cmd installhull] in its constructor.  The normal way
3642 to do this is as follows:
3643
3644 [para]
3645 [example {snit::widgetadaptor mywidget {
3646     # ...
3647     constructor {args} {
3648         # ...
3649         installhull using text -foreground white
3650         # ...
3651     }
3652     # ...
3653 }
3654 }]
3655 [para]
3656
3657 In this case, the [cmd installhull] command will create the hull using
3658 a command like this:
3659
3660 [para]
3661 [example {    set hull [text $win -foreground white]
3662 }]
3663 [para]
3664
3665 The hull is a [cmd text] widget, so its widget class is [const Text].  Just
3666 as with [cmd snit::widget] hulls, Snit assumes that it will pick up
3667 all of its normal option values automatically, without help from Snit.
3668 Options delegated from a different name are initialized from the
3669 option database in the same way as described above.
3670
3671 [para]
3672
3673 In earlier versions of Snit, [cmd snit::widgetadaptor]s were expected
3674 to call [cmd installhull] like this:
3675
3676 [para]
3677 [example {    installhull [text $win -foreground white]
3678 }]
3679 [para]
3680
3681 This form still works--but Snit will not query the option database as
3682 described above.
3683
3684 [subsection {How does Snit initialize options delegated to other components?}]
3685
3686 For hull components, Snit assumes that Tk will do most of the work
3687 automatically.  Non-hull components are somewhat more complicated, because
3688 they are matched against the option database twice.
3689
3690 [para]
3691
3692 A component widget remains a widget still, and is therefore
3693 initialized from the option database in the usual way.  A [cmd text]
3694 widget remains a [cmd text] widget whether it is a component of a
3695 megawidget or not, and will be created as such.
3696
3697 [para]
3698
3699 But then, the option database is queried for all options delegated to
3700 the component, and the component is initialized accordingly--provided
3701 that the [cmd install] command is used to create it.
3702
3703 [para]
3704
3705 Before option database support was added to Snit, the usual way to
3706 create a component was to simply create it in the constructor and
3707 assign its command name to the component variable:
3708
3709 [para]
3710 [example {snit::widget mywidget {
3711     delegate option -background to myComp
3712
3713     constructor {args} {
3714         set myComp [text $win.text -foreground black]
3715     }
3716 }
3717 }]
3718 [para]
3719
3720 The drawback of this method is that Snit has no opportunity to
3721 initialize the component properly.  Hence, the following approach is
3722 now used:
3723
3724 [para]
3725 [example {snit::widget mywidget {
3726     delegate option -background to myComp
3727
3728     constructor {args} {
3729         install myComp using text $win.text -foreground black
3730     }
3731 }
3732 }]
3733 [para]
3734
3735 The [cmd install] command does the following:
3736
3737 [para]
3738 [list_begin itemized]
3739
3740 [item]
3741
3742 Builds a list of the options explicitly included in the [cmd install]
3743 command--in this case, [const -foreground].
3744
3745 [item]
3746
3747 Queries the option database for all options delegated explicitly to
3748 the named component.
3749
3750 [item]
3751
3752 Creates the component using the specified command, after inserting
3753 into it a list of options and values read from the option database.
3754 Thus, the explicitly included options (like [const -foreground]) will 
3755 override anything read from the option database.
3756
3757 [item]
3758
3759 If the widget definition implicitly delegated options to the component
3760 using [cmd {delegate option *}], then Snit calls the newly created
3761 component's [cmd configure] method to receive a list of all of the
3762 component's options.  From this Snit builds a list of options
3763 implicitly delegated to the component which were not explicitly
3764 included in the [cmd install] command.  For all such options, Snit
3765 queries the option database and configures the component accordingly.
3766
3767 [list_end]
3768
3769 You don't really need to know all of this; just use [cmd install] to
3770 install your components, and Snit will try to do the right thing.
3771
3772 [subsection {What happens if I install a non-widget as a component of widget?}]
3773
3774 A [cmd snit::type] never queries the option database.
3775 However, a [cmd snit::widget] can have non-widget components.  And if
3776 options are delegated to those components, and if the [cmd install]
3777 command is used to install those components, then they will be
3778 initialized from the option database just as widget components are.
3779
3780 [para]
3781
3782 However, when used within a megawidget, [cmd install] assumes that the
3783 created component uses a reasonably standard widget-like creation
3784 syntax.  If it doesn't, don't use [cmd install].
3785
3786 [section {ENSEMBLE COMMANDS}]
3787
3788 [subsection {What is an ensemble command?}]
3789
3790 An ensemble command is a command with subcommands.  Snit objects are
3791 all ensemble commands; however, the term more usually refers to
3792 commands like the standard Tcl commands [cmd string], [cmd file], 
3793 and [cmd clock].  In a sense, these are singleton objects--there's
3794 only one instance of them.
3795
3796 [subsection {How can I create an ensemble command using Snit?}]
3797
3798 There are two ways--as a [cmd snit::type], or as an instance of
3799 a [cmd snit::type].
3800
3801 [subsection {How can I create an ensemble command using an instance of a snit::type?}]
3802
3803 Define a type whose [sectref {INSTANCE METHODS}] are the subcommands
3804 of your ensemble command.  Then, create an instance of the type with
3805 the desired name.
3806
3807 [para]
3808
3809 For example, the following code uses [sectref {DELEGATION}] to create
3810 a work-alike for the standard [cmd string] command:
3811
3812 [example {snit::type ::mynamespace::mystringtype {
3813     delegate method * to stringhandler
3814
3815     constructor {} {
3816         set stringhandler string
3817     }
3818 }
3819
3820 ::mynamespace::mystringtype mystring
3821 }]
3822
3823 We create the type in a namespace, so that the type command is hidden;
3824 then we create a single instance with the desired name--
3825 [cmd mystring], in this case.
3826
3827 [para]
3828
3829 This method has two drawbacks.  First, it leaves the type command
3830 floating about.  More seriously, your shiny new ensemble
3831 command will have [method info] and [method destroy] subcommands that
3832 you probably have no use for.  But read on.
3833
3834 [subsection {How can I create an ensemble command using a snit::type?}]
3835
3836 Define a type whose [sectref {TYPE METHODS}] are the subcommands
3837 of your ensemble command.[para]
3838
3839 For example, the following code uses [sectref {DELEGATION}] to create
3840 a work-alike for the standard [cmd string] command:
3841
3842 [example {snit::type mystring {
3843     delegate typemethod * to stringhandler
3844
3845     typeconstructor {
3846         set stringhandler string
3847     }
3848 }
3849 }]
3850
3851 Now the type command itself is your ensemble command.
3852
3853 [para]
3854
3855 This method has only one drawback, and though it's major, it's 
3856 also surmountable.  Your new ensemble command will have
3857 [method create], [method info] and [method destroy] subcommands
3858 you don't want.  And worse yet, since the [method create] method
3859 can be implicit, users of your command will accidentally be creating
3860 instances of your [cmd mystring] type if they should mispell one
3861 of the subcommands.  The command will succeed--the first time--but
3862 won't do what's wanted.  This is very bad.
3863
3864 [para]
3865
3866 The work around is to set some [sectref {PRAGMAS}], as shown here:
3867
3868 [example {snit::type mystring {
3869     pragma -hastypeinfo    no 
3870     pragma -hastypedestroy no 
3871     pragma -hasinstances   no
3872
3873     delegate typemethod * to stringhandler
3874
3875     typeconstructor {
3876         set stringhandler string
3877     }
3878 }
3879 }]
3880
3881 Here we've used the [cmd pragma] statement to tell Snit that we don't
3882 want the [method info] typemethod or the [method destroy] typemethod,
3883 and that our type has no instances; this eliminates the 
3884 [method create] typemethod and all related code.  As
3885 a result, our ensemble command will be well-behaved, with no
3886 unexpected subcommands.
3887
3888 [section {PRAGMAS}]
3889
3890 [subsection {What is a pragma?}]
3891
3892 A pragma is an option you can set in your type definitions that
3893 affects how the type is defined and how it works once it is defined.
3894
3895 [subsection {How do I set a pragma?}]
3896
3897 Use the [cmd pragma] statement.  Each pragma is an option with a
3898 value; each time you use the [cmd pragma] statement you can set one or
3899 more of them.
3900
3901 [subsection {How can I get rid of the "info" type method?}]
3902
3903 Set the [const -hastypeinfo] pragma to [const no]:
3904
3905 [example {snit::type dog {
3906     pragma -hastypeinfo no
3907     # ...
3908 }
3909 }]
3910
3911 Snit will refrain from defining the [method info] type method.
3912
3913 [subsection {How can I get rid of the "destroy" type method?}]
3914
3915 Set the [const -hastypedestroy] pragma to [const no]:
3916
3917 [example {snit::type dog {
3918     pragma -hastypedestroy no
3919     # ...
3920 }
3921 }]
3922
3923 Snit will refrain from defining the [method destroy] type method.
3924
3925 [subsection {How can I get rid of the "create" type method?}]
3926
3927 Set the [const -hasinstances] pragma to [const no]:
3928
3929 [example {snit::type dog {
3930     pragma -hasinstances no
3931     # ...
3932 }
3933 }]
3934
3935 Snit will refrain from defining the [method create] type method;
3936 if you call the type command with an unknown method name, you'll get
3937 an error instead of a new instance of the type.
3938
3939 [para]
3940
3941 This is useful if you wish to use a [cmd snit::type] to define
3942 an ensemble command rather than a type with instances.
3943
3944 [para]
3945
3946 Pragmas [const -hastypemethods] and [const -hasinstances] cannot
3947 both be false (or there'd be nothing left).
3948
3949 [subsection {How can I get rid of type methods altogether?}]
3950
3951 Normal Tk widget type commands don't have subcommands; all they do is 
3952 create widgets--in Snit terms, the type command calls the 
3953 [method create] type method directly.  To get the same behavior from 
3954 Snit, set the [const -hastypemethods] pragma to [const no]:
3955
3956 [example {snit::type dog {
3957     pragma -hastypemethods no
3958     #...
3959 }
3960
3961 # Creates ::spot
3962 dog spot
3963
3964 # Tries to create an instance called ::create
3965 dog create spot
3966 }]
3967
3968 Pragmas [const -hastypemethods] and [const -hasinstances] cannot
3969 both be false (or there'd be nothing left).
3970
3971 [subsection {Why can't I create an object that replaces an old object with the same name?}]
3972
3973 Up until Snit 0.95, you could use any name for an instance of a 
3974 [cmd snit::type], even if the name was already in use by some other
3975 object or command.  You could do the following, for example:
3976
3977 [example {snit::type dog { ... }
3978
3979 dog proc
3980 }]
3981
3982 You now have a new dog named "proc", which is probably not something
3983 that you really wanted to do.  As a result, Snit now throws an error
3984 if your chosen instance name names an existing command.  To restore
3985 the old behavior, set the [const -canreplace] pragma to [const yes]:
3986
3987 [example {snit::type dog {
3988     pragma -canreplace yes
3989     # ...
3990 }
3991 }]
3992
3993 [subsection {How can I make my simple type run faster?}]
3994
3995 In Snit 1.x, you can set the [const -simpledispatch] pragma to [const yes].
3996
3997 [para]
3998
3999 Snit 1.x method dispatch is both flexible and fast, but the flexibility
4000 comes with a price.  If your type doesn't require the flexibility, the 
4001 [const -simpledispatch] pragma allows you to substitute a simpler
4002 dispatch mechanism that runs quite a bit faster.  The limitations
4003 are these:
4004
4005 [list_begin itemized]
4006
4007 [item] Methods cannot be delegated.
4008 [item] [cmd uplevel] and [cmd upvar] do not work as expected: the
4009 caller's scope is two levels up rather than one.
4010 [item] The option-handling methods 
4011 ([cmd cget], [cmd configure], and [cmd configurelist]) are very
4012 slightly slower.
4013 [list_end]
4014
4015 In Snit 2.2, the [const -simpledispatch] macro is obsolete, and
4016 ignored; all Snit 2.2 method dispatch is faster than Snit 1.x's 
4017 [const -simpledispatch].
4018
4019 [section {MACROS}]
4020
4021 [subsection {What is a macro?}]
4022
4023 A Snit macro is nothing more than a Tcl proc that's defined in the 
4024 Tcl interpreter used to compile Snit type definitions.
4025
4026 [subsection {What are macros good for?}]
4027
4028 You can use Snit macros to define new type definition syntax, and to
4029 support conditional compilation.
4030
4031 [subsection {How do I do conditional compilation?}]
4032
4033 Suppose you want your type to use a fast C extension if it's
4034 available; otherwise, you'll fallback to a slower Tcl implementation.
4035 You want to define one set of methods in the first case, and another
4036 set in the second case.  But how can your type definition know whether
4037 the fast C extension is available or not?
4038
4039 [para]
4040
4041 It's easily done.  Outside of any type definition, define a macro that
4042 returns 1 if the extension is available, and 0 otherwise:
4043
4044 [example {if {$gotFastExtension} {
4045     snit::macro fastcode {} {return 1}
4046 } else {
4047     snit::macro fastcode {} {return 0}
4048 }
4049 }]
4050
4051 Then, use your macro in your type definition:
4052
4053 [example {snit::type dog {
4054
4055     if {[fastcode]} {
4056         # Fast methods
4057         method bark {} {...}
4058         method wagtail {} {...}
4059     } else {
4060         # Slow methods
4061         method bark {} {...}
4062         method wagtail {} {...}
4063     }
4064 }
4065 }]
4066
4067 [subsection {How do I define new type definition syntax?}]
4068
4069 Use a macro.  For example, your [cmd snit::widget]'s 
4070 [const -background] option should be propagated to a number
4071 of component widgets.  You could implement that like this:
4072
4073 [example {snit::widget mywidget {
4074     option -background -default white -configuremethod PropagateBackground
4075
4076     method PropagateBackground {option value} {
4077         $comp1 configure $option $value
4078         $comp2 configure $option $value
4079         $comp3 configure $option $value
4080     }
4081 }
4082 }]
4083
4084 For one option, this is fine; if you've got a number of options, it
4085 becomes tedious and error prone.  So package it as a macro:
4086
4087 [example {snit::macro propagate {option "to" components} {
4088     option $option -configuremethod Propagate$option
4089
4090     set body "\n"
4091
4092     foreach comp $components {
4093         append body "\$$comp configure $option \$value\n"
4094     }
4095
4096     method Propagate$option {option value} $body
4097 }
4098 }]
4099
4100 Then you can use it like this:
4101
4102 [example {snit::widget mywidget {
4103     option -background default -white
4104     option -foreground default -black
4105
4106     propagate -background to {comp1 comp2 comp3}
4107     propagate -foreground to {comp1 comp2 comp3}
4108 }
4109 }]
4110
4111 [subsection {Are there are restrictions on macro names?}]
4112
4113 Yes, there are.  You can't redefine any standard Tcl commands or Snit
4114 type definition statements.  You can use any other command name,
4115 including the name of a previously defined macro.
4116
4117 [para]
4118
4119 If you're using Snit macros in your application, go ahead and name
4120 them in the global namespace, as shown above.  But if you're using
4121 them to define types or widgets for use by others, you should define
4122 your macros in the same namespace as your types or widgets.  That way,
4123 they won't conflict with other people's macros.
4124
4125 [para]
4126
4127 If my fancy [cmd snit::widget] is called [cmd ::mylib::mywidget], 
4128 for example, then I should define my [cmd propagate] macro as
4129 [cmd ::mylib::propagate]:
4130
4131
4132 [example {snit::macro mylib::propagate {option "to" components} { ... }
4133
4134 snit::widget ::mylib::mywidget {
4135     option -background default -white
4136     option -foreground default -black
4137
4138     mylib::propagate -background to {comp1 comp2 comp3}
4139     mylib::propagate -foreground to {comp1 comp2 comp3}
4140 }
4141 }]
4142
4143
4144 [section {BUGS, IDEAS, FEEDBACK}]
4145
4146 This document, and the package it describes, will undoubtedly contain
4147 bugs and other problems.
4148
4149 Please report such in the category [emph snit] of the
4150 [uri {http://sourceforge.net/tracker/?group_id=12883} {Tcllib SF Trackers}].
4151
4152 Please also report any ideas for enhancements you may have for either
4153 package and/or documentation.
4154
4155
4156 [keywords class {object oriented} object C++]
4157 [keywords {Incr Tcl} BWidget]
4158 [keywords widget adaptors {widget adaptors} {mega widget}]
4159 [manpage_end]