Version 3 of WhoAmI? -Letting proceedurally added widgets know their names

Updated 2005-09-01 07:35:38

WJG (1st September 2005) There's probably something described in the small print of the Tcl man pages that will do something similar but... If I add new functionality to an app I like to pack buttons 'n' stuff on the fly in which case there is no guarentee as to what a widget name might be. Widget bindings allow us to know which item was clicked although the button -command switch has no such choice. To cross this gap we have to work with references. Because the 'bind all' take presidence over the individual button command we can use a binding to set a global variable which subsequent commands can access.

The following code example allows us to create buttons and then allows the button command to make adjustments to itself.

 #----------------------------------------------------------------
 # whoami.tcl
 #----------------------------------------------------------------
 #
 # Making a button aware of just who it is.
 # This can be useful if wigets are built proceedurally and pathnames
 # are not defined explicitly.
 #
 #----------------------------------------------------------------

 # set global array for where the last 2 B1 events occured
 array set ::widget {
   active ""
   last ""
 }

 bind all <Button-1> {
  set ::widget(last) $::widget(active)
  set ::widget(active) %W
 }

 #----------------------------------------------------------------
 proc whoami {} {
  if {[$::widget(active) cget -text] == "Clickme!"} {
    $::widget(active) config -text "Clicked!"
    } else {
    $::widget(active) config -text "Clickme!"
    }
  puts "I am \"[winfo name ${::widget(active)}]\" and I live in \"[winfo parent ${::widget(active)}]\"."
 }

 #----------------------------------------------------------------

 console show 
 expr srand(1)
 set base .t2 
 toplevel $base

 button .b1 -text Clickme! -command {
   whoami
   # use randomly created path names
   set i [string trimleft [expr rand()] 0.]
   pack [button $base.b$i -text "Button $i" -command whoami]
 }
 pack .b1

 bind .b1 <Button-1> {puts "I am %W -hello from my unique <B1> binding."}