123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- #
- # ttk::treeview widget bindings and utilities.
- #
- namespace eval ttk::treeview {
- variable State
- # Enter/Leave/Motion
- #
- set State(activeWidget) {}
- set State(activeHeading) {}
- # Press/drag/release:
- #
- set State(pressMode) none
- set State(pressX) 0
- # For pressMode == "resize"
- set State(resizeColumn) #0
- # For pressmode == "heading"
- set State(heading) {}
- }
- ### Widget bindings.
- #
- bind Treeview <Motion> { ttk::treeview::Motion %W %x %y }
- bind Treeview <B1-Leave> { #nothing }
- bind Treeview <Leave> { ttk::treeview::ActivateHeading {} {}}
- bind Treeview <Button-1> { ttk::treeview::Press %W %x %y }
- bind Treeview <Double-Button-1> { ttk::treeview::DoubleClick %W %x %y }
- bind Treeview <ButtonRelease-1> { ttk::treeview::Release %W %x %y }
- bind Treeview <B1-Motion> { ttk::treeview::Drag %W %x %y }
- bind Treeview <Up> { ttk::treeview::Keynav %W up }
- bind Treeview <Down> { ttk::treeview::Keynav %W down }
- bind Treeview <Right> { ttk::treeview::Keynav %W right }
- bind Treeview <Left> { ttk::treeview::Keynav %W left }
- bind Treeview <Prior> { %W yview scroll -1 pages }
- bind Treeview <Next> { %W yview scroll 1 pages }
- bind Treeview <Return> { ttk::treeview::ToggleFocus %W }
- bind Treeview <space> { ttk::treeview::ToggleFocus %W }
- bind Treeview <Shift-Button-1> \
- { ttk::treeview::Select %W %x %y extend }
- bind Treeview <<ToggleSelection>> \
- { ttk::treeview::Select %W %x %y toggle }
- ttk::copyBindings TtkScrollable Treeview
- ### Binding procedures.
- #
- ## Keynav -- Keyboard navigation
- #
- # @@@ TODO: verify/rewrite up and down code.
- #
- proc ttk::treeview::Keynav {w dir} {
- set focus [$w focus]
- if {$focus eq ""} { return }
- switch -- $dir {
- up {
- if {[set up [$w prev $focus]] eq ""} {
- set focus [$w parent $focus]
- } else {
- while {[$w item $up -open] && [llength [$w children $up]]} {
- set up [lindex [$w children $up] end]
- }
- set focus $up
- }
- }
- down {
- if {[$w item $focus -open] && [llength [$w children $focus]]} {
- set focus [lindex [$w children $focus] 0]
- } else {
- set up $focus
- while {$up ne "" && [set down [$w next $up]] eq ""} {
- set up [$w parent $up]
- }
- set focus $down
- }
- }
- left {
- if {[$w item $focus -open] && [llength [$w children $focus]]} {
- CloseItem $w $focus
- } else {
- set focus [$w parent $focus]
- }
- }
- right {
- OpenItem $w $focus
- }
- }
- if {$focus != {}} {
- SelectOp $w $focus choose
- }
- }
- ## Motion -- pointer motion binding.
- # Sets cursor, active element ...
- #
- proc ttk::treeview::Motion {w x y} {
- variable State
- ttk::saveCursor $w State(userConfCursor) [ttk::cursor hresize]
- set cursor $State(userConfCursor)
- set activeHeading {}
- switch -- [$w identify region $x $y] {
- separator { set cursor hresize }
- heading { set activeHeading [$w identify column $x $y] }
- }
- ttk::setCursor $w $cursor
- ActivateHeading $w $activeHeading
- }
- ## ActivateHeading -- track active heading element
- #
- proc ttk::treeview::ActivateHeading {w heading} {
- variable State
- if {$w != $State(activeWidget) || $heading != $State(activeHeading)} {
- if {[winfo exists $State(activeWidget)] && $State(activeHeading) != {}} {
- # It may happen that $State(activeHeading) no longer corresponds
- # to an existing display column. This happens for instance when
- # changing -displaycolumns in a bound script when this change
- # triggers a <Leave> event. A proc checking if the display column
- # $State(activeHeading) is really still present or not could be
- # written but it would need to check several special cases:
- # a. -displaycolumns "#all" or being an explicit columns list
- # b. column #0 display is not governed by the -displaycolumn
- # list but by the value of the -show option
- # --> Let's rather catch the following line.
- catch {$State(activeWidget) heading $State(activeHeading) state !active}
- }
- if {$heading != {}} {
- $w heading $heading state active
- }
- set State(activeHeading) $heading
- set State(activeWidget) $w
- }
- }
- ## Select $w $x $y $selectop
- # Binding procedure for selection operations.
- # See "Selection modes", below.
- #
- proc ttk::treeview::Select {w x y op} {
- if {[set item [$w identify row $x $y]] ne "" } {
- SelectOp $w $item $op
- }
- }
- ## DoubleClick -- Double-Button-1 binding.
- #
- proc ttk::treeview::DoubleClick {w x y} {
- if {[set row [$w identify row $x $y]] ne ""} {
- Toggle $w $row
- } else {
- Press $w $x $y ;# perform single-click action
- }
- }
- ## Press -- Button binding.
- #
- proc ttk::treeview::Press {w x y} {
- focus $w
- switch -- [$w identify region $x $y] {
- nothing { }
- heading { heading.press $w $x $y }
- separator { resize.press $w $x $y }
- tree -
- cell {
- set item [$w identify item $x $y]
- SelectOp $w $item choose
- switch -glob -- [$w identify element $x $y] {
- *indicator -
- *disclosure { Toggle $w $item }
- }
- }
- }
- }
- ## Drag -- B1-Motion binding
- #
- proc ttk::treeview::Drag {w x y} {
- variable State
- switch $State(pressMode) {
- resize { resize.drag $w $x }
- heading { heading.drag $w $x $y }
- }
- }
- proc ttk::treeview::Release {w x y} {
- variable State
- switch $State(pressMode) {
- resize { resize.release $w $x }
- heading { heading.release $w }
- }
- set State(pressMode) none
- Motion $w $x $y
- }
- ### Interactive column resizing.
- #
- proc ttk::treeview::resize.press {w x y} {
- variable State
- set State(pressMode) "resize"
- set State(resizeColumn) [$w identify column $x $y]
- }
- proc ttk::treeview::resize.drag {w x} {
- variable State
- $w drag $State(resizeColumn) $x
- }
- proc ttk::treeview::resize.release {w x} {
- $w drop
- }
- ### Heading activation.
- #
- proc ttk::treeview::heading.press {w x y} {
- variable State
- set column [$w identify column $x $y]
- set State(pressMode) "heading"
- set State(heading) $column
- $w heading $column state pressed
- }
- proc ttk::treeview::heading.drag {w x y} {
- variable State
- if { [$w identify region $x $y] eq "heading"
- && [$w identify column $x $y] eq $State(heading)
- } {
- $w heading $State(heading) state pressed
- } else {
- $w heading $State(heading) state !pressed
- }
- }
- proc ttk::treeview::heading.release {w} {
- variable State
- if {[lsearch -exact [$w heading $State(heading) state] pressed] >= 0} {
- after 0 [$w heading $State(heading) -command]
- }
- $w heading $State(heading) state !pressed
- }
- ### Selection modes.
- #
- ## SelectOp $w $item [ choose | extend | toggle ] --
- # Dispatch to appropriate selection operation
- # depending on current value of -selectmode.
- #
- proc ttk::treeview::SelectOp {w item op} {
- select.$op.[$w cget -selectmode] $w $item
- }
- ## -selectmode none:
- #
- proc ttk::treeview::select.choose.none {w item} { $w focus $item; $w see $item }
- proc ttk::treeview::select.toggle.none {w item} { $w focus $item; $w see $item }
- proc ttk::treeview::select.extend.none {w item} { $w focus $item; $w see $item }
- ## -selectmode browse:
- #
- proc ttk::treeview::select.choose.browse {w item} { BrowseTo $w $item }
- proc ttk::treeview::select.toggle.browse {w item} { BrowseTo $w $item }
- proc ttk::treeview::select.extend.browse {w item} { BrowseTo $w $item }
- ## -selectmode multiple:
- #
- proc ttk::treeview::select.choose.extended {w item} {
- BrowseTo $w $item
- }
- proc ttk::treeview::select.toggle.extended {w item} {
- $w selection toggle [list $item]
- }
- proc ttk::treeview::select.extend.extended {w item} {
- if {[set anchor [$w focus]] ne ""} {
- $w selection set [between $w $anchor $item]
- } else {
- BrowseTo $w $item
- }
- }
- ### Tree structure utilities.
- #
- ## between $tv $item1 $item2 --
- # Returns a list of all items between $item1 and $item2,
- # in preorder traversal order. $item1 and $item2 may be
- # in either order.
- #
- # NOTES:
- # This routine is O(N) in the size of the tree.
- # There's probably a way to do this that's O(N) in the number
- # of items returned, but I'm not clever enough to figure it out.
- #
- proc ttk::treeview::between {tv item1 item2} {
- variable between [list]
- variable selectingBetween 0
- ScanBetween $tv $item1 $item2 {}
- return $between
- }
- ## ScanBetween --
- # Recursive worker routine for ttk::treeview::between
- #
- proc ttk::treeview::ScanBetween {tv item1 item2 item} {
- variable between
- variable selectingBetween
- if {$item eq $item1 || $item eq $item2} {
- lappend between $item
- set selectingBetween [expr {!$selectingBetween}]
- } elseif {$selectingBetween} {
- lappend between $item
- }
- foreach child [$tv children $item] {
- ScanBetween $tv $item1 $item2 $child
- }
- }
- ### User interaction utilities.
- #
- ## OpenItem, CloseItem -- Set the open state of an item, generate event
- #
- proc ttk::treeview::OpenItem {w item} {
- $w focus $item
- event generate $w <<TreeviewOpen>>
- $w item $item -open true
- }
- proc ttk::treeview::CloseItem {w item} {
- $w item $item -open false
- $w focus $item
- event generate $w <<TreeviewClose>>
- }
- ## Toggle -- toggle opened/closed state of item
- #
- proc ttk::treeview::Toggle {w item} {
- # don't allow toggling on indicators that
- # are not present in front of leaf items
- if {[$w children $item] == {}} {
- return
- }
- # not a leaf, toggle!
- if {[$w item $item -open]} {
- CloseItem $w $item
- } else {
- OpenItem $w $item
- }
- }
- ## ToggleFocus -- toggle opened/closed state of focus item
- #
- proc ttk::treeview::ToggleFocus {w} {
- set item [$w focus]
- if {$item ne ""} {
- Toggle $w $item
- }
- }
- ## BrowseTo -- navigate to specified item; set focus and selection
- #
- proc ttk::treeview::BrowseTo {w item} {
- $w see $item
- $w focus $item
- $w selection set [list $item]
- }
- #*EOF*
|