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