1# $Id$ 2# 3# ttk::treeview widget bindings and utilities. 4# 5 6namespace eval ttk::treeview { 7 variable State 8 9 # Enter/Leave/Motion 10 # 11 set State(activeWidget) {} 12 set State(activeHeading) {} 13 14 # Press/drag/release: 15 # 16 set State(pressMode) none 17 set State(pressX) 0 18 19 # For pressMode == "resize" 20 set State(resizeColumn) #0 21 22 # For pressmode == "heading" 23 set State(heading) {} 24} 25 26### Widget bindings. 27# 28 29bind Treeview <Motion> { ttk::treeview::Motion %W %x %y } 30bind Treeview <B1-Leave> { #nothing } 31bind Treeview <Leave> { ttk::treeview::ActivateHeading {} {}} 32bind Treeview <ButtonPress-1> { ttk::treeview::Press %W %x %y } 33bind Treeview <Double-ButtonPress-1> { ttk::treeview::DoubleClick %W %x %y } 34bind Treeview <ButtonRelease-1> { ttk::treeview::Release %W %x %y } 35bind Treeview <B1-Motion> { ttk::treeview::Drag %W %x %y } 36bind Treeview <KeyPress-Up> { ttk::treeview::Keynav %W up } 37bind Treeview <KeyPress-Down> { ttk::treeview::Keynav %W down } 38bind Treeview <KeyPress-Right> { ttk::treeview::Keynav %W right } 39bind Treeview <KeyPress-Left> { ttk::treeview::Keynav %W left } 40bind Treeview <KeyPress-Prior> { %W yview scroll -1 pages } 41bind Treeview <KeyPress-Next> { %W yview scroll 1 pages } 42bind Treeview <KeyPress-Return> { ttk::treeview::ToggleFocus %W } 43bind Treeview <KeyPress-space> { ttk::treeview::ToggleFocus %W } 44 45bind Treeview <Shift-ButtonPress-1> \ 46 { ttk::treeview::Select %W %x %y extend } 47bind Treeview <Control-ButtonPress-1> \ 48 { ttk::treeview::Select %W %x %y toggle } 49 50ttk::copyBindings TtkScrollable Treeview 51 52### Binding procedures. 53# 54 55## Keynav -- Keyboard navigation 56# 57# @@@ TODO: verify/rewrite up and down code. 58# 59proc ttk::treeview::Keynav {w dir} { 60 set focus [$w focus] 61 if {$focus eq ""} { return } 62 63 switch -- $dir { 64 up { 65 if {[set up [$w prev $focus]] eq ""} { 66 set focus [$w parent $focus] 67 } else { 68 while {[$w item $up -open] && [llength [$w children $up]]} { 69 set up [lindex [$w children $up] end] 70 } 71 set focus $up 72 } 73 } 74 down { 75 if {[$w item $focus -open] && [llength [$w children $focus]]} { 76 set focus [lindex [$w children $focus] 0] 77 } else { 78 set up $focus 79 while {$up ne "" && [set down [$w next $up]] eq ""} { 80 set up [$w parent $up] 81 } 82 set focus $down 83 } 84 } 85 left { 86 if {[$w item $focus -open] && [llength [$w children $focus]]} { 87 CloseItem $w $focus 88 } else { 89 set focus [$w parent $focus] 90 } 91 } 92 right { 93 OpenItem $w $focus 94 } 95 } 96 97 if {$focus != {}} { 98 SelectOp $w $focus choose 99 } 100} 101 102## Motion -- pointer motion binding. 103# Sets cursor, active element ... 104# 105proc ttk::treeview::Motion {w x y} { 106 set cursor {} 107 set activeHeading {} 108 109 switch -- [$w identify region $x $y] { 110 separator { set cursor hresize } 111 heading { set activeHeading [$w identify column $x $y] } 112 } 113 114 ttk::setCursor $w $cursor 115 ActivateHeading $w $activeHeading 116} 117 118## ActivateHeading -- track active heading element 119# 120proc ttk::treeview::ActivateHeading {w heading} { 121 variable State 122 123 if {$w != $State(activeWidget) || $heading != $State(activeHeading)} { 124 if {$State(activeHeading) != {}} { 125 $State(activeWidget) heading $State(activeHeading) state !active 126 } 127 if {$heading != {}} { 128 $w heading $heading state active 129 } 130 set State(activeHeading) $heading 131 set State(activeWidget) $w 132 } 133} 134 135## Select $w $x $y $selectop 136# Binding procedure for selection operations. 137# See "Selection modes", below. 138# 139proc ttk::treeview::Select {w x y op} { 140 if {[set item [$w identify row $x $y]] ne "" } { 141 SelectOp $w $item $op 142 } 143} 144 145## DoubleClick -- Double-ButtonPress-1 binding. 146# 147proc ttk::treeview::DoubleClick {w x y} { 148 if {[set row [$w identify row $x $y]] ne ""} { 149 Toggle $w $row 150 } else { 151 Press $w $x $y ;# perform single-click action 152 } 153} 154 155## Press -- ButtonPress binding. 156# 157proc ttk::treeview::Press {w x y} { 158 focus $w 159 switch -- [$w identify region $x $y] { 160 nothing { } 161 heading { heading.press $w $x $y } 162 separator { resize.press $w $x $y } 163 tree - 164 cell { 165 set item [$w identify item $x $y] 166 SelectOp $w $item choose 167 switch -glob -- [$w identify element $x $y] { 168 *indicator - 169 *disclosure { Toggle $w $item } 170 } 171 } 172 } 173} 174 175## Drag -- B1-Motion binding 176# 177proc ttk::treeview::Drag {w x y} { 178 variable State 179 switch $State(pressMode) { 180 resize { resize.drag $w $x } 181 heading { heading.drag $w $x $y } 182 } 183} 184 185proc ttk::treeview::Release {w x y} { 186 variable State 187 switch $State(pressMode) { 188 resize { resize.release $w $x } 189 heading { heading.release $w } 190 } 191 set State(pressMode) none 192 Motion $w $x $y 193} 194 195### Interactive column resizing. 196# 197proc ttk::treeview::resize.press {w x y} { 198 variable State 199 set State(pressMode) "resize" 200 set State(resizeColumn) [$w identify column $x $y] 201} 202 203proc ttk::treeview::resize.drag {w x} { 204 variable State 205 $w drag $State(resizeColumn) $x 206} 207 208proc ttk::treeview::resize.release {w x} { 209 # no-op 210} 211 212### Heading activation. 213# 214 215proc ttk::treeview::heading.press {w x y} { 216 variable State 217 set column [$w identify column $x $y] 218 set State(pressMode) "heading" 219 set State(heading) $column 220 $w heading $column state pressed 221} 222 223proc ttk::treeview::heading.drag {w x y} { 224 variable State 225 if { [$w identify region $x $y] eq "heading" 226 && [$w identify column $x $y] eq $State(heading) 227 } { 228 $w heading $State(heading) state pressed 229 } else { 230 $w heading $State(heading) state !pressed 231 } 232} 233 234proc ttk::treeview::heading.release {w} { 235 variable State 236 if {[lsearch -exact [$w heading $State(heading) state] pressed] >= 0} { 237 after 0 [$w heading $State(heading) -command] 238 } 239 $w heading $State(heading) state !pressed 240} 241 242### Selection modes. 243# 244 245## SelectOp $w $item [ choose | extend | toggle ] -- 246# Dispatch to appropriate selection operation 247# depending on current value of -selectmode. 248# 249proc ttk::treeview::SelectOp {w item op} { 250 select.$op.[$w cget -selectmode] $w $item 251} 252 253## -selectmode none: 254# 255proc ttk::treeview::select.choose.none {w item} { $w focus $item } 256proc ttk::treeview::select.toggle.none {w item} { $w focus $item } 257proc ttk::treeview::select.extend.none {w item} { $w focus $item } 258 259## -selectmode browse: 260# 261proc ttk::treeview::select.choose.browse {w item} { BrowseTo $w $item } 262proc ttk::treeview::select.toggle.browse {w item} { BrowseTo $w $item } 263proc ttk::treeview::select.extend.browse {w item} { BrowseTo $w $item } 264 265## -selectmode multiple: 266# 267proc ttk::treeview::select.choose.extended {w item} { 268 BrowseTo $w $item 269} 270proc ttk::treeview::select.toggle.extended {w item} { 271 $w selection toggle [list $item] 272} 273proc ttk::treeview::select.extend.extended {w item} { 274 if {[set anchor [$w focus]] ne ""} { 275 $w selection set [between $w $anchor $item] 276 } else { 277 BrowseTo $w $item 278 } 279} 280 281### Tree structure utilities. 282# 283 284## between $tv $item1 $item2 -- 285# Returns a list of all items between $item1 and $item2, 286# in preorder traversal order. $item1 and $item2 may be 287# in either order. 288# 289# NOTES: 290# This routine is O(N) in the size of the tree. 291# There's probably a way to do this that's O(N) in the number 292# of items returned, but I'm not clever enough to figure it out. 293# 294proc ttk::treeview::between {tv item1 item2} { 295 variable between [list] 296 variable selectingBetween 0 297 ScanBetween $tv $item1 $item2 {} 298 return $between 299} 300 301## ScanBetween -- 302# Recursive worker routine for ttk::treeview::between 303# 304proc ttk::treeview::ScanBetween {tv item1 item2 item} { 305 variable between 306 variable selectingBetween 307 308 if {$item eq $item1 || $item eq $item2} { 309 lappend between $item 310 set selectingBetween [expr {!$selectingBetween}] 311 } elseif {$selectingBetween} { 312 lappend between $item 313 } 314 foreach child [$tv children $item] { 315 ScanBetween $tv $item1 $item2 $child 316 } 317} 318 319### User interaction utilities. 320# 321 322## OpenItem, CloseItem -- Set the open state of an item, generate event 323# 324 325proc ttk::treeview::OpenItem {w item} { 326 $w focus $item 327 event generate $w <<TreeviewOpen>> 328 $w item $item -open true 329} 330 331proc ttk::treeview::CloseItem {w item} { 332 $w item $item -open false 333 $w focus $item 334 event generate $w <<TreeviewClose>> 335} 336 337## Toggle -- toggle opened/closed state of item 338# 339proc ttk::treeview::Toggle {w item} { 340 if {[$w item $item -open]} { 341 CloseItem $w $item 342 } else { 343 OpenItem $w $item 344 } 345} 346 347## ToggleFocus -- toggle opened/closed state of focus item 348# 349proc ttk::treeview::ToggleFocus {w} { 350 set item [$w focus] 351 if {$item ne ""} { 352 Toggle $w $item 353 } 354} 355 356## BrowseTo -- navigate to specified item; set focus and selection 357# 358proc ttk::treeview::BrowseTo {w item} { 359 $w see $item 360 $w focus $item 361 $w selection set [list $item] 362} 363 364#*EOF* 365