1# 2# $Id$ 3# 4# Bindings for Buttons, Checkbuttons, and Radiobuttons. 5# 6# Notes: <Button1-Leave>, <Button1-Enter> only control the "pressed" 7# state; widgets remain "active" if the pointer is dragged out. 8# This doesn't seem to be conventional, but it's a nice way 9# to provide extra feedback while the grab is active. 10# (If the button is released off the widget, the grab deactivates and 11# we get a <Leave> event then, which turns off the "active" state) 12# 13# Normally, <ButtonRelease> and <ButtonN-Enter/Leave> events are 14# delivered to the widget which received the initial <ButtonPress> 15# event. However, Tk [grab]s (#1223103) and menu interactions 16# (#1222605) can interfere with this. To guard against spurious 17# <Button1-Enter> events, the <Button1-Enter> binding only sets 18# the pressed state if the button is currently active. 19# 20 21namespace eval ttk::button {} 22 23bind TButton <Enter> { %W instate !disabled {%W state active} } 24bind TButton <Leave> { %W state !active } 25bind TButton <Key-space> { ttk::button::activate %W } 26bind TButton <<Invoke>> { ttk::button::activate %W } 27 28bind TButton <ButtonPress-1> \ 29 { %W instate !disabled { ttk::clickToFocus %W; %W state pressed } } 30bind TButton <ButtonRelease-1> \ 31 { %W instate {pressed !disabled} { %W state !pressed; %W invoke } } 32bind TButton <Button1-Leave> \ 33 { %W state !pressed } 34bind TButton <Button1-Enter> \ 35 { %W instate {active !disabled} { %W state pressed } } 36 37# Checkbuttons and Radiobuttons have the same bindings as Buttons: 38# 39ttk::copyBindings TButton TCheckbutton 40ttk::copyBindings TButton TRadiobutton 41 42# ...plus a few more: 43 44bind TRadiobutton <KeyPress-Up> { ttk::button::RadioTraverse %W -1 } 45bind TRadiobutton <KeyPress-Down> { ttk::button::RadioTraverse %W +1 } 46 47# bind TCheckbutton <KeyPress-plus> { %W select } 48# bind TCheckbutton <KeyPress-minus> { %W deselect } 49 50# activate -- 51# Simulate a button press: temporarily set the state to 'pressed', 52# then invoke the button. 53# 54proc ttk::button::activate {w} { 55 $w instate disabled { return } 56 set oldState [$w state pressed] 57 update idletasks; after 100 ;# block event loop to avoid reentrancy 58 $w state $oldState 59 $w invoke 60} 61 62# RadioTraverse -- up/down keyboard traversal for radiobutton groups. 63# Set focus to previous/next radiobutton in a group. 64# A radiobutton group consists of all the radiobuttons with 65# the same parent and -variable; this is a pretty good heuristic 66# that works most of the time. 67# 68proc ttk::button::RadioTraverse {w dir} { 69 set group [list] 70 foreach sibling [winfo children [winfo parent $w]] { 71 if { [winfo class $sibling] eq "TRadiobutton" 72 && [$sibling cget -variable] eq [$w cget -variable] 73 && ![$sibling instate disabled] 74 } { 75 lappend group $sibling 76 } 77 } 78 79 if {![llength $group]} { # Shouldn't happen, but can. 80 return 81 } 82 83 set pos [expr {([lsearch -exact $group $w] + $dir) % [llength $group]}] 84 tk::TabToWindow [lindex $group $pos] 85} 86