📄 tree.tcl
字号:
set index [lsearch $data($parent) $node] set xli [expr {$xi-[Widget::getoption $path -deltax]-5}] } set yl $ys } else { # position is before $node # drop position is before $node in children of parent of $node set parent [lindex $data($node) 0] set index [expr {[lsearch $data($parent) $node] - 1}] set xli [expr {$xi-[Widget::getoption $path -deltax]-5}] set yl $yi } lappend target [list $parent $index] set vmode [expr {$vmode | 2}] } else { lappend target {} } if { ($vmode & 3) == 3 } { # result have both node and position # we compute what is the preferred method if { $yc-$yi <= 3 || $ys-$yc <= 3 } { lappend target "position" } else { lappend target "node" } } } } if { $vmode && [set cmd [Widget::getoption $path -dropovercmd]] != "" } { # user-defined dropover command set res [uplevel \#0 $cmd [list $path $source $target $op $type $dnddata]] set code [lindex $res 0] set newmode 0 if { $code & 1 } { # update vmode set mode [lindex $res 1] if { ($vmode & 1) && ![string compare $mode "node"] } { set newmode 1 } elseif { ($vmode & 2) && ![string compare $mode "position"] } { set newmode 2 } elseif { ($vmode & 4) && ![string compare $mode "widget"] } { set newmode 4 } } set vmode $newmode } else { if { ($vmode & 3) == 3 } { # result have both item and position # we choose the preferred method if { ![string compare [lindex $target 3] "position"] } { set vmode [expr {$vmode & ~1}] } else { set vmode [expr {$vmode & ~2}] } } if { $data(dnd,mode) == 4 || $data(dnd,mode) == 0 } { # dropovermode is widget or empty - recall is not necessary set code 1 } else { set code 3 } } if {!$data(dnd,empty)} { # draw dnd visual following vmode if { $vmode & 1 } { set data(dnd,node) [list "node" [lindex $target 1]] $path.c create rectangle $xi $yi $xs $ys -tags drop } elseif { $vmode & 2 } { set data(dnd,node) [concat "position" [lindex $target 2]] $path.c create line $xli [expr {$yl-$dy/2}] $xli $yl $xs $yl -tags drop } elseif { $vmode & 4 } { set data(dnd,node) [list "widget"] } else { set code [expr {$code & 2}] } } if { $code & 1 } { DropSite::setcursor based_arrow_down } else { DropSite::setcursor dot } return $code}# ----------------------------------------------------------------------------# Command Tree::_auto_scroll# ----------------------------------------------------------------------------proc Tree::_auto_scroll { path x y } { variable $path upvar 0 $path data set xmax [winfo width $path] set ymax [winfo height $path] set scroll {} if { $y <= 6 } { if { [lindex [$path.c yview] 0] > 0 } { set scroll [list yview -1] DropSite::setcursor sb_up_arrow } } elseif { $y >= $ymax-6 } { if { [lindex [$path.c yview] 1] < 1 } { set scroll [list yview 1] DropSite::setcursor sb_down_arrow } } elseif { $x <= 6 } { if { [lindex [$path.c xview] 0] > 0 } { set scroll [list xview -1] DropSite::setcursor sb_left_arrow } } elseif { $x >= $xmax-6 } { if { [lindex [$path.c xview] 1] < 1 } { set scroll [list xview 1] DropSite::setcursor sb_right_arrow } } if { [string length $data(dnd,afterid)] && [string compare $data(dnd,scroll) $scroll] } { after cancel $data(dnd,afterid) set data(dnd,afterid) "" } set data(dnd,scroll) $scroll if { [string length $scroll] && ![string length $data(dnd,afterid)] } { set data(dnd,afterid) [after 200 Tree::_scroll $path $scroll] } return $data(dnd,afterid)}# ----------------------------------------------------------------------------# Command Tree::_scroll# ----------------------------------------------------------------------------proc Tree::_scroll { path cmd dir } { variable $path upvar 0 $path data if { ($dir == -1 && [lindex [$path.c $cmd] 0] > 0) || ($dir == 1 && [lindex [$path.c $cmd] 1] < 1) } { $path.c $cmd scroll $dir units set data(dnd,afterid) [after 100 Tree::_scroll $path $cmd $dir] } else { set data(dnd,afterid) "" DropSite::setcursor dot }}# Tree::_keynav --## Handle navigational keypresses on the tree.## Arguments:# which tag indicating the direction of motion:# up move to the node graphically above current# down move to the node graphically below current# left close current if open, else move to parent# right open current if closed, else move to child# open open current if closed, close current if open# win name of the tree widget## Results:# None.proc Tree::_keynav {which win} { # Keyboard navigation is riddled with special cases. In order to avoid # the complex logic, we will instead make a list of all the visible, # selectable nodes, then do a simple next or previous operation. # One easy way to get all of the visible nodes is to query the canvas # object for all the items with the "node" tag; since the tree is always # completely redrawn, this list will be in vertical order. set nodes {} foreach nodeItem [$win.c find withtag node] { set node [Tree::_get_node_name $win $nodeItem 2] if { [Widget::cget $win.$node -selectable] } { lappend nodes $node } } # Keyboard navigation is all relative to the current node # surles: Get the current node for single or multiple selection schemas. set node [_get_current_node $win] switch -exact -- $which { "up" { # Up goes to the node that is vertically above the current node # (NOT necessarily the current node's parent) if { [string equal $node ""] } { return } set index [lsearch $nodes $node] incr index -1 if { $index >= 0 } { $win selection set [lindex $nodes $index] _set_current_node $win [lindex $nodes $index] $win see [lindex $nodes $index] return } } "down" { # Down goes to the node that is vertically below the current node if { [string equal $node ""] } { $win selection set [lindex $nodes 0] _set_current_node $win [lindex $nodes 0] $win see [lindex $nodes 0] return } set index [lsearch $nodes $node] incr index if { $index < [llength $nodes] } { $win selection set [lindex $nodes $index] _set_current_node $win [lindex $nodes $index] $win see [lindex $nodes $index] return } } "right" { # On a right arrow, if the current node is closed, open it. # If the current node is open, go to its first child if { [string equal $node ""] } { return } set open [$win itemcget $node -open] if { $open } { if { [llength [$win nodes $node]] } { set index [lsearch $nodes $node] incr index if { $index < [llength $nodes] } { $win selection set [lindex $nodes $index] _set_current_node $win [lindex $nodes $index] $win see [lindex $nodes $index] return } } } else { $win itemconfigure $node -open 1 if { [set cmd [Widget::getoption $win -opencmd]] != "" } { uplevel \#0 $cmd $node } return } } "left" { # On a left arrow, if the current node is open, close it. # If the current node is closed, go to its parent. if { [string equal $node ""] } { return } set open [$win itemcget $node -open] if { $open } { $win itemconfigure $node -open 0 if { [set cmd [Widget::getoption $win -closecmd]] != "" } { uplevel \#0 $cmd $node } return } else { set parent [$win parent $node] if { [string equal $parent "root"] } { set parent $node } else { while { ![$win itemcget $parent -selectable] } { set parent [$win parent $parent] if { [string equal $parent "root"] } { set parent $node break } } } $win selection set $parent _set_current_node $win $parent $win see $parent return } } "space" { if { [string equal $node ""] } { return } set open [$win itemcget $node -open] if { [llength [$win nodes $node]] } { # Toggle the open status of the chosen node. $win itemconfigure $node -open [expr {$open?0:1}] if {$open} { # Node was open, is now closed. Call the close-cmd if { [set cmd [Widget::getoption $win -closecmd]] != "" } { uplevel \#0 $cmd $node } } else { # Node was closed, is now open. Call the open-cmd if { [set cmd [Widget::getoption $win -opencmd]] != "" } { uplevel \#0 $cmd $node } } } } } return}# Tree::_get_current_node --## Get the current node for either single or multiple# node selection trees. If the tree allows for # multiple selection, return the cursor node. Otherwise,# if there is a selection, return the first node in the# list. If there is no selection, return the root node.## arguments:# win name of the tree widget## Results:# The current node.proc Tree::_get_current_node {win} { if {[info exists selectTree::selectCursor($win)]} { set result $selectTree::selectCursor($win) } elseif {[set selList [$win selection get]] != {}} { set result [lindex $selList 0] } else { set result "" } return $result}# Tree::_set_current_node --## Set the current node for either single or multiple# node selection trees.## arguments:# win Name of the tree widget# node The current node.## Results:# None.proc Tree::_set_current_node {win node} { if {[info exists selectTree::selectCursor($win)]} { set selectTree::selectCursor($win) $node } return}# Tree::_get_node_name --## Given a canvas item, get the name of the tree node represented by that# item.## Arguments:# path tree to query# item Optional canvas item to examine; if omitted, # defaults to "current"# tagindex Optional tag index, since the n:nodename tag is not# in the same spot for all canvas items. If omitted,# defaults to "end-1", so it works with "current" item.## Results:# node name of the tree node.proc Tree::_get_node_name {path {item current} {tagindex end-1}} { return [string range [lindex [$path.c gettags $item] $tagindex] 2 end]}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -