See [What is a Megawidget]? for megawidget info. ---- Some people have been asking (on news:comp.lang.tcl) for the Tk core to be modified so that widgets all carry with them some additional user data. This is not necessary. The following script illustrates how you can do this without all that paraphernalia in pure Tcl... proc substvars {varlist script} { foreach varname $varlist { upvar $varname var regsub -all %%${varname}%% $script [list $var] script } return $script } foreach class { button checkbutton radiobutton menubutton menu label message frame toplevel scrollbar scale text canvas } { rename $class userdata'enabled'$class proc $class {pathname args} [substvars class { set class %%class%% set w [eval [list userdata'enabled'$class $pathname] $args] rename $w userdata'enabled'$w upvar #0 ::userdata'data ary set ary($w) {} proc $w {subcommand args} [substvars w { set w %%w%% if {![string compare $subcommand "setUserData"]} { upvar #0 ::userdata'data ary switch [llength $args] { 0 { return $ary($w) } 1 { set ary($w) [lindex $args 0] return } default { return -code error "wrong # args: should be\ \"$w setUserData ?value?\"" } } } else { return [uplevel userdata'enabled'$w $subcommand $args] } }] return $w }] } I'll leave adding the finishing flourishes (like making the error messages take account of the new command, and deleting the user data and the proc when the widget is destroyed) up to others for now. '''DKF''' ---- '''Vince writes''' it is not necessary, indeed, but it could still be desirable. The code you have here is pretty dense, and if you also add the cleanup code, error message fixing code, etc, it's going to become even more impenetrable (and perhaps slow?). That's when one has to think about a providing a simple set of C hooks to Tk to let this happen very simply. I do think the speed issue can be a problem, especially when you add handling and fixing of error conditions. The problem is that a lot of Tk's .tcl library contains code like this (from tkTextInsert): catch { if {[$w compare sel.first <= insert] \ && [$w compare sel.last >= insert]} { $w delete sel.first sel.last } } which, if the '$w' is a wrapped object, can generate a massive error traceback, which then has to be discarded. (This is a general disadvantage of all the 'rename' styles of changing the behaviour of Tk's core widgets). In this particular case, Tk's library should be changed to be: # New version which doesn't use 'catch', to avoid # generating a long stack trace every time the window doesn't # have a current selection proc tkTextInsert {w s} { if {[string equal $s ""] || [string equal [$w cget -state] "disabled"]} { return } if {[llength [$w tag ranges sel]]} { if {[$w compare sel.first <= insert] \ && [$w compare sel.last >= insert]} { $w delete sel.first sel.last } } $w insert insert $s $w see insert } but there are other examples where such changes are not possible. (e.g. in menus, there is no 'entryexists' sub-command, so we need to use a catch). ---- [Category GUI]