Version 8 of widget:repeaterButton

Updated 2002-05-24 20:47:33

GPS - Sun Mar 10, 2002: I looked at some code to a button that repeated an action and found it to be overly complex, so that inspired me to whip up this concise little tool.


  #!/bin/wish8.3
  #updated Thu May 9, 2002
  #eval button $win $args was changed to
  #eval button [concat $win $args]

  proc bind:copyClass {class newClass} {
    set bindingList [bind $class]
    #puts $bindingList

    foreach binding $bindingList {
      bind $newClass $binding [bind $class $binding]
    }
  }

  proc widget:repeaterButton:ButtonPress-1 {win} {
    eval [$win cget -command]
    if {$::buttonPressed == 1} {
      $win configure -relief sunken
      after 20 "widget:repeaterButton:ButtonPress-1 $win"
    }
  }

  proc widget:repeaterButton:ButtonRelease-1 {win} {
    $win configure -relief raised
  }

  proc widget:repeaterButton {win args} {
    bind:copyClass Button RepeaterButton

    bind RepeaterButton <ButtonPress-1> "set ::buttonPressed 1; \
      widget:repeaterButton:ButtonPress-1 %W"
    bind RepeaterButton <ButtonRelease-1> "set ::buttonPressed 0; \
      widget:repeaterButton:ButtonRelease-1 %W"

    eval button [concat $win $args]

    bindtags $win "RepeaterButton all"
    return $win
  }


  #test code
  catch {console show}
  pack [widget:repeaterButton .rb -text "Say Hello" -command "puts HELLO"]

It's nice, but it repeats too fast, I think. Is there a way to slow it down?

AK - What happens when you increase the timeout of the after command ?

GPS: I'm glad you like it. Increasing the after timeout as AK suggested will fix the issue. Also, note the update to it above which uses concat to fix an issue with passing some arguments.


JPT : I've found your code very interesting, and decided to propose a version that allows the creation of multiple repeaterButtons by the use of individual proc and variables for each new instance (I left aside the "bindtags" command, not knowing exactly what's its purpose).

  proc RepeaterButton {w args} {
    proc ${w}_command {w} {
     if {![set ::${w}_ok]} {
       $w config -relief raised
       return
     }
     $w config -relief sunken
     uplevel eval [$w cget -command]
     after 50 "${w}_command $w"
    }
    catch {destroy $w}
    eval button [concat $w $args]
    bind $w <ButtonPress-1> {set ::%W_ok 1; %W_command %W}
    bind $w <ButtonRelease-1> {set ::%W_ok 0}
    return $w
  }

  pack [RepeaterButton  .rb -text incr -command {incr i}]
  pack [RepeaterButton  .rb2 -text decr -command {incr i -1}]
  pack [label .l -textvariable i]
  set i 0

;#


GPS I used the bindtags command to remove the default bindings for a button, and replace them with my modified bindings. Using uplevel to eval the -command is a good idea. I'm glad you were able to adapt the code for your own use. :)