[Richard Suchenwirth] 2001-01-19 - Overloading a widget means writing a new widget proc with the same name and (at least) same functionality, so when Tcl/Tk (e.g. pack) calls it internally, it reacts in the same way. This is the lightweight way of creating "mini-megawidgets" in pure Tcl without much hassle, e.g. something like this: proc supertext {w args} { eval text $w $args ;# create the "base" thing rename $w _$w ;# keep the original widget command # Here comes the overloaded widget proc: proc $w {cmd args} { set self [lindex [info level 0] 0] ;# get name I was called with switch -- $cmd { super {puts "super! $args" ;# added method} default {uplevel 1 _$self $cmd $args} } } return $w ;# like the original "text" command } supertext .t -foreground red pack .t -fill both -expand 1 .t insert end "This is a.. (see stdout)" .t super example This way, a supertext "inherits" all the behavior of a text widget, but in addition has the (here very stupid) "super" method. You can also overload the configure/cget "methods", but make sure the original "instance variables" are still passed through to the original widget proc. Adding "method names" like above is the easiest. See also [ANSI color control] for ''ansicolor::text'', a text widget where the ''insert'' command is intercepted to process color control escape sequences. ---- '''DKF:''' you can do even better for yourself if you use interpreter command aliases (i.e. your code can be simpler, more robust and less heavily nested, all by taking advantage of the ability to add extra arguments to the command via the alias - [RS]: which in functional programming circles is called "currying" - see [Custom curry].) Taking the example listed above: proc supertext {w args} { eval text $w $args ;# create the "base" thing rename $w _$w ;# keep the original widget command # Install the alias... interp alias {} $w {} supertext_instanceCmd $w return $w ;# like the original "text" command } proc supertext_instanceCmd {self cmd args} { switch -- $cmd { super {puts "super! $args" ;# added method} default {return [uplevel 1 [list _$self $cmd] $args]} } } supertext .t -foreground red pack .t -fill both -expand 1 .t insert end "This is a.. (see stdout)" .t super example This comes even more into its own when combined with namespaces and multiple interpreters. [WHD]: But note that this method can get you into trouble if your overloaded widget command is overloaded a second time. I forget the specifics, but the problem arises if the overloaded widget is destroyed. You have to un-overload in exactly the reverse order, and it doesn't quite work. ---- [TR] Here is another method with the same result, but without using [rename] at all. This was inspired by the discussion, that rename invalidates the byte compiled representation [http://groups-beta.google.com/group/comp.lang.tcl/browse_frm/thread/3791969747e86489/159d22e0d70a908?hl=en&lr=&rnum=2&prev=/groups%3Fq%3Drename%2Balias%26hl%3Dde%26lr%3D%26group%3Dcomp.lang.tcl.*%26scoring%3Dd%26selm%3D41C083F0.6080000%2540bardo.clearlight.com%26rnum%3D2#159d22e0d70a908]: proc supertext {w args} { # create the "base" thing: eval text $w $args # hide the original widget command, but keep it: interp hide {} $w # Install the alias: interp alias {} $w {} supertext_instanceCmd $w # like the original "text" command: return $w } proc supertext_instanceCmd {self cmd args} { puts "supertext_instanceCmd $self $cmd $args" switch -- $cmd { super {puts "super! $args" ;# added method} default {return [uplevel 1 [list interp invokehidden {} $self $cmd] $args]} } } supertext .t -foreground red pack .t -fill both -expand 1 .t insert end "This is a.. (see stdout)" .t super example The original widget command is hidden from the current interpreter and the alias is installed like in the previous example. The instanceCmd call this hidden command in order to do the default work, that is not cusomized. [RS]: The widget name [rename]d is just something like an alias, linking to the instance in C code.. so I expect no bytecode to lose, no performance loss by using [rename]. But 'interp hide/invokehidden' is an interesting alternative... ---- Question: Is there an easy way to add your own configure options to widgets? I know the trick of using an array with the same name as the widget, and doing bind widget {unset %W} but using this is extremely verbose: array set $widget [list key value] lindex [array get $widget key] 1 What I'd really like is to just add my own option which could be handled by the existing configure and cget widget commands. Failing that, I'll settle for custom versions of configure and cget which wrap around the standard ones, provided that they can accept a mix of my custom options with the built-in options. ---- A more meaningful example was triggered by a c.l.t post from [Bryan Oakley]: ''it'd be nice to create text like "some things are *bold* and some are _underlined_" and be able to put that into a widget with a single call.'' Here's a quick shot: proc markuptext {w args} { eval [list text $w] $args rename ::$w ::_$w proc ::$w {cmd args} { set w [lindex [info level 1] 0] switch -- $cmd { insert {eval [list markuptext'insert $w] $args} default {eval [list ::_$w $cmd] $args} } } set w } proc markuptext'insert {w position args} { if {[llength $args]==1} {set args [lindex $args 0]} foreach word [split $args] { if {$word==""} continue set tag "" if {[regexp {^\*(.+)\*$} $word -> word]} {set tag bold} if {[regexp {^_(.+)_$} $word -> word]} {set tag underline} ::_$w insert $position "$word " $tag } } #----------------------------- Test and demo code... pack [markuptext .t] .t tag configure bold -font {Arial 10 bold} .t tag configure underline -font {Arial 10 underline} .t insert end "Test for *bold* and _underlined_ words...\ with \"quotes\" and \{unbalanced braces" ---- [LV] There are several examples for markup languages. For instance, this wiki uses '''' to mark a request for emphasis (italics) and '''''' as a request for strong (bold) highlighting. This wiki doesn't have a notation for underlining. Then there's [setext] which uses similar markup as you've implemented. And there is a [mime] [rich text] (not the same as the [microsoft] rich text) which has its own markup. ---- [Arts and crafts of Tcl-Tk programming] [Category GUI] [Category Widget]