Pierre Coueffin 20-Oct-2006
I often find myself programming interactively using the tclreadline binding. During this process I end up sourcing the same file repeatedly.
In order to allow me to define widgets in the file without getting errors when I source the file next time, I wrote a proc called needwidget:
proc needwidget {w cmds} { if {[info command $w] == {}} { uplevel $cmds } }
This allowed me to wrap the call to create the widget up neatly:
needwidget .button { pack [button .button -text foo] }
When I think that I'm done hacking on the code, I unwrap the calls to remove clutter.... I used this method for several years, but I have become disenchanted with the wasted effort and risk of introducing typos that it produces.
Today I came up with something that I like much better:
proc rewidget class { if {[llength [info commands create_$class]] != 0} { return } rename $class create_$class interp alias {} $class {} create_or_configure $class } proc create_or_configure {class w args} { if {[llength [info commands $w]] != 0} { if {[string match \ [string tolower [winfo class $w]] \ [string tolower $class]]} { eval [concat [list $w configure] $args] return $w } else { destroy $w } } return [eval [concat [list create_$class $w] $args]] } foreach w { button canvas entry frame listbox menu menubutton scale scrollbar spinbox toplevel } { rewidget $w }
What this code does is alter the behavior of the core widget commands to make them create the widget if it does not exist, but only re-configure them if they already exist. If you try to change the class of a given widget, it will destroy the original one, and create it as if it had not existed... this may play havoc with your existing layout. If you have a problem with that, you might want to change the "destroy..." line to throw an error.