PageRenderTime 64ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/grass-6.4.2/lib/external/bwidget/tree.tcl

#
TCL | 1389 lines | 1001 code | 184 blank | 204 comment | 232 complexity | 2b6b8c4a9f7770b6c2b51c3cf1d8e87e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, 0BSD, BSD-3-Clause
  1. # ------------------------------------------------------------------------------
  2. # tree.tcl
  3. # This file is part of Unifix BWidget Toolkit
  4. # $Id: tree.tcl 10192 2002-01-24 19:25:32Z radim $
  5. # ------------------------------------------------------------------------------
  6. # Index of commands:
  7. # - Tree::create
  8. # - Tree::configure
  9. # - Tree::cget
  10. # - Tree::insert
  11. # - Tree::itemconfigure
  12. # - Tree::itemcget
  13. # - Tree::bindText
  14. # - Tree::bindImage
  15. # - Tree::delete
  16. # - Tree::move
  17. # - Tree::reorder
  18. # - Tree::selection
  19. # - Tree::exists
  20. # - Tree::parent
  21. # - Tree::index
  22. # - Tree::nodes
  23. # - Tree::see
  24. # - Tree::opentree
  25. # - Tree::closetree
  26. # - Tree::edit
  27. # - Tree::xview
  28. # - Tree::yview
  29. # - Tree::_update_edit_size
  30. # - Tree::_destroy
  31. # - Tree::_see
  32. # - Tree::_recexpand
  33. # - Tree::_subdelete
  34. # - Tree::_update_scrollregion
  35. # - Tree::_cross_event
  36. # - Tree::_draw_node
  37. # - Tree::_draw_subnodes
  38. # - Tree::_update_nodes
  39. # - Tree::_draw_tree
  40. # - Tree::_redraw_tree
  41. # - Tree::_redraw_selection
  42. # - Tree::_redraw_idle
  43. # - Tree::_drag_cmd
  44. # - Tree::_drop_cmd
  45. # - Tree::_over_cmd
  46. # - Tree::_auto_scroll
  47. # - Tree::_scroll
  48. # ------------------------------------------------------------------------------
  49. namespace eval Tree {
  50. namespace eval Node {
  51. Widget::declare Tree::Node {
  52. {-text String "" 0}
  53. {-font TkResource "" 0 listbox}
  54. {-image TkResource "" 0 label}
  55. {-window String "" 0}
  56. {-fill TkResource black 0 {listbox -foreground}}
  57. {-data String "" 0}
  58. {-open Boolean 0 0}
  59. {-drawcross Enum auto 0 {auto allways never}}
  60. }
  61. }
  62. Widget::tkinclude Tree canvas :cmd \
  63. remove {-insertwidth -insertbackground -insertborderwidth -insertofftime \
  64. -insertontime -selectborderwidth -closeenough -confine -scrollregion \
  65. -xscrollincrement -yscrollincrement -width -height} \
  66. initialize {-relief sunken -borderwidth 2 -takefocus 1 \
  67. -highlightthickness 1 -width 200}
  68. Widget::declare Tree {
  69. {-deltax Int 10 0 {=0 ""}}
  70. {-deltay Int 15 0 {=0 ""}}
  71. {-padx Int 20 0 {=0 ""}}
  72. {-background TkResource "" 0 listbox}
  73. {-selectbackground TkResource "" 0 listbox}
  74. {-selectforeground TkResource "" 0 listbox}
  75. {-width TkResource "" 0 listbox}
  76. {-height TkResource "" 0 listbox}
  77. {-showlines Boolean 1 0}
  78. {-linesfill TkResource black 0 {frame -background}}
  79. {-linestipple TkResource "" 0 {label -bitmap}}
  80. {-redraw Boolean 1 0}
  81. {-opencmd String "" 0}
  82. {-closecmd String "" 0}
  83. {-dropovermode Flag "wpn" 0 "wpn"}
  84. {-bg Synonym -background}
  85. }
  86. DragSite::include Tree "TREE_NODE" 1
  87. DropSite::include Tree {
  88. TREE_NODE {copy {} move {}}
  89. }
  90. Widget::addmap Tree "" :cmd {-deltay -yscrollincrement}
  91. proc ::Tree { path args } { return [eval Tree::create $path $args] }
  92. proc use {} {}
  93. variable _edit
  94. }
  95. # ------------------------------------------------------------------------------
  96. # Command Tree::create
  97. # ------------------------------------------------------------------------------
  98. proc Tree::create { path args } {
  99. variable $path
  100. upvar 0 $path data
  101. Widget::init Tree $path $args
  102. set data(root) {{}}
  103. set data(selnodes) {}
  104. set data(upd,level) 0
  105. set data(upd,nodes) {}
  106. set data(upd,afterid) ""
  107. set data(dnd,scroll) ""
  108. set data(dnd,afterid) ""
  109. set data(dnd,selnodes) {}
  110. set data(dnd,node) ""
  111. set path [eval canvas $path [Widget::subcget $path :cmd] \
  112. -width [expr {[Widget::getoption $path -width]*8}] \
  113. -height [expr {[Widget::getoption $path -height]*[Widget::getoption $path -deltay]}] \
  114. -xscrollincrement 8]
  115. $path bind cross <ButtonPress-1> {Tree::_cross_event %W}
  116. bind $path <Configure> "Tree::_update_scrollregion $path"
  117. bind $path <Destroy> "Tree::_destroy $path"
  118. DragSite::setdrag $path $path Tree::_init_drag_cmd [Widget::getoption $path -dragendcmd] 1
  119. DropSite::setdrop $path $path Tree::_over_cmd Tree::_drop_cmd 1
  120. rename $path ::$path:cmd
  121. proc ::$path { cmd args } "return \[eval Tree::\$cmd $path \$args\]"
  122. return $path
  123. }
  124. # ------------------------------------------------------------------------------
  125. # Command Tree::configure
  126. # ------------------------------------------------------------------------------
  127. proc Tree::configure { path args } {
  128. variable $path
  129. upvar 0 $path data
  130. set res [Widget::configure $path $args]
  131. set ch1 [expr {[Widget::hasChanged $path -deltax val] |
  132. [Widget::hasChanged $path -deltay dy] |
  133. [Widget::hasChanged $path -padx val] |
  134. [Widget::hasChanged $path -showlines val]}]
  135. set ch2 [expr {[Widget::hasChanged $path -selectbackground val] |
  136. [Widget::hasChanged $path -selectforeground val]}]
  137. if { [Widget::hasChanged $path -linesfill fill] |
  138. [Widget::hasChanged $path -linestipple stipple] } {
  139. $path:cmd itemconfigure line -fill $fill -stipple $stipple
  140. $path:cmd itemconfigure cross -foreground $fill
  141. }
  142. if { $ch1 } {
  143. _redraw_idle $path 3
  144. } elseif { $ch2 } {
  145. _redraw_idle $path 1
  146. }
  147. if { [Widget::hasChanged $path -height h] } {
  148. $path:cmd configure -height [expr {$h*$dy}]
  149. }
  150. if { [Widget::hasChanged $path -width w] } {
  151. $path:cmd configure -width [expr {$w*8}]
  152. }
  153. if { [Widget::hasChanged $path -redraw bool] && $bool } {
  154. set upd $data(upd,level)
  155. set data(upd,level) 0
  156. _redraw_idle $path $upd
  157. }
  158. set force [Widget::hasChanged $path -dragendcmd dragend]
  159. DragSite::setdrag $path $path Tree::_init_drag_cmd $dragend $force
  160. DropSite::setdrop $path $path Tree::_over_cmd Tree::_drop_cmd
  161. return $res
  162. }
  163. # ------------------------------------------------------------------------------
  164. # Command Tree::cget
  165. # ------------------------------------------------------------------------------
  166. proc Tree::cget { path option } {
  167. return [Widget::cget $path $option]
  168. }
  169. # ------------------------------------------------------------------------------
  170. # Command Tree::insert
  171. # ------------------------------------------------------------------------------
  172. proc Tree::insert { path index parent node args } {
  173. variable $path
  174. upvar 0 $path data
  175. if { [info exists data($node)] } {
  176. return -code error "node \"$node\" already exists"
  177. }
  178. if { ![info exists data($parent)] } {
  179. return -code error "node \"$parent\" does not exist"
  180. }
  181. Widget::init Tree::Node $path.$node $args
  182. if { ![string compare $index "end"] } {
  183. lappend data($parent) $node
  184. } else {
  185. incr index
  186. set data($parent) [linsert $data($parent) $index $node]
  187. }
  188. set data($node) [list $parent]
  189. if { ![string compare $parent "root"] } {
  190. _redraw_idle $path 3
  191. } elseif { [visible $path $parent] } {
  192. # parent is visible...
  193. if { [Widget::getoption $path.$parent -open] } {
  194. # ...and opened -> redraw whole
  195. _redraw_idle $path 3
  196. } else {
  197. # ...and closed -> redraw cross
  198. lappend data(upd,nodes) $parent 8
  199. _redraw_idle $path 2
  200. }
  201. }
  202. return $node
  203. }
  204. # ------------------------------------------------------------------------------
  205. # Command Tree::itemconfigure
  206. # ------------------------------------------------------------------------------
  207. proc Tree::itemconfigure { path node args } {
  208. variable $path
  209. upvar 0 $path data
  210. if { ![string compare $node "root"] || ![info exists data($node)] } {
  211. return -code error "node \"$node\" does not exist"
  212. }
  213. set result [Widget::configure $path.$node $args]
  214. if { [visible $path $node] } {
  215. set lopt {}
  216. set flag 0
  217. foreach opt {-window -image -drawcross -font -text -fill} {
  218. set flag [expr {$flag << 1}]
  219. if { [Widget::hasChanged $path.$node $opt val] } {
  220. set flag [expr {$flag | 1}]
  221. }
  222. }
  223. if { [Widget::hasChanged $path.$node -open val] } {
  224. _redraw_idle $path 3
  225. } elseif { $data(upd,level) < 3 && $flag } {
  226. if { [set idx [lsearch $data(upd,nodes) $node]] == -1 } {
  227. lappend data(upd,nodes) $node $flag
  228. } else {
  229. incr idx
  230. set flag [expr {[lindex $data(upd,nodes) $idx] | $flag}]
  231. set data(upd,nodes) [lreplace $data(upd,nodes) $idx $idx $flag]
  232. }
  233. _redraw_idle $path 2
  234. }
  235. }
  236. return $result
  237. }
  238. # ------------------------------------------------------------------------------
  239. # Command Tree::itemcget
  240. # ------------------------------------------------------------------------------
  241. proc Tree::itemcget { path node option } {
  242. variable $path
  243. upvar 0 $path data
  244. if { ![string compare $node "root"] || ![info exists data($node)] } {
  245. return -code error "node \"$node\" does not exist"
  246. }
  247. return [Widget::cget $path.$node $option]
  248. }
  249. # ------------------------------------------------------------------------------
  250. # Command Tree::bindText
  251. # ------------------------------------------------------------------------------
  252. proc Tree::bindText { path event script } {
  253. if { $script != "" } {
  254. $path:cmd bind "node" $event \
  255. "$script \[string range \[lindex \[$path:cmd gettags current\] 1\] 2 end\]"
  256. } else {
  257. $path:cmd bind "node" $event {}
  258. }
  259. }
  260. # ------------------------------------------------------------------------------
  261. # Command Tree::bindImage
  262. # ------------------------------------------------------------------------------
  263. proc Tree::bindImage { path event script } {
  264. if { $script != "" } {
  265. $path:cmd bind "img" $event \
  266. "$script \[string range \[lindex \[$path:cmd gettags current\] 1\] 2 end\]"
  267. } else {
  268. $path:cmd bind "img" $event {}
  269. }
  270. }
  271. # ------------------------------------------------------------------------------
  272. # Command Tree::delete
  273. # ------------------------------------------------------------------------------
  274. proc Tree::delete { path args } {
  275. variable $path
  276. upvar 0 $path data
  277. foreach lnodes $args {
  278. foreach node $lnodes {
  279. if { [string compare $node "root"] && [info exists data($node)] } {
  280. set parent [lindex $data($node) 0]
  281. set idx [lsearch $data($parent) $node]
  282. set data($parent) [lreplace $data($parent) $idx $idx]
  283. _subdelete $path [list $node]
  284. }
  285. }
  286. }
  287. set sel $data(selnodes)
  288. set data(selnodes) {}
  289. eval selection $path set $sel
  290. _redraw_idle $path 3
  291. }
  292. # ------------------------------------------------------------------------------
  293. # Command Tree::move
  294. # ------------------------------------------------------------------------------
  295. proc Tree::move { path parent node index } {
  296. variable $path
  297. upvar 0 $path data
  298. if { ![string compare $node "root"] || ![info exists data($node)] } {
  299. return -code error "node \"$node\" does not exist"
  300. }
  301. if { ![info exists data($parent)] } {
  302. return -code error "node \"$parent\" does not exist"
  303. }
  304. set p $parent
  305. while { [string compare $p "root"] } {
  306. if { ![string compare $p $node] } {
  307. return -code error "node \"$parent\" is a descendant of \"$node\""
  308. }
  309. set p [parent $path $p]
  310. }
  311. set oldp [lindex $data($node) 0]
  312. set idx [lsearch $data($oldp) $node]
  313. set data($oldp) [lreplace $data($oldp) $idx $idx]
  314. set data($node) [concat [list $parent] [lrange $data($node) 1 end]]
  315. if { ![string compare $index "end"] } {
  316. lappend data($parent) $node
  317. } else {
  318. incr index
  319. set data($parent) [linsert $data($parent) $index $node]
  320. }
  321. if { (![string compare $oldp "root"] ||
  322. ([visible $path $oldp] && [Widget::getoption $path.$oldp -open])) ||
  323. (![string compare $parent "root"] ||
  324. ([visible $path $parent] && [Widget::getoption $path.$parent -open])) } {
  325. _redraw_idle $path 3
  326. }
  327. }
  328. # ------------------------------------------------------------------------------
  329. # Command Tree::reorder
  330. # ------------------------------------------------------------------------------
  331. proc Tree::reorder { path node neworder } {
  332. variable $path
  333. upvar 0 $path data
  334. if { ![info exists data($node)] } {
  335. return -code error "node \"$node\" does not exist"
  336. }
  337. set children [lrange $data($node) 1 end]
  338. if { [llength $children] } {
  339. set children [BWidget::lreorder $children $neworder]
  340. set data($node) [linsert $children 0 [lindex $data($node) 0]]
  341. if { [visible $path $node] && [Widget::getoption $path.$node -open] } {
  342. _redraw_idle $path 3
  343. }
  344. }
  345. }
  346. # ------------------------------------------------------------------------------
  347. # Command Tree::selection
  348. # ------------------------------------------------------------------------------
  349. proc Tree::selection { path cmd args } {
  350. variable $path
  351. upvar 0 $path data
  352. switch -- $cmd {
  353. set {
  354. set data(selnodes) {}
  355. foreach node $args {
  356. if { [info exists data($node)] } {
  357. if { [lsearch $data(selnodes) $node] == -1 } {
  358. lappend data(selnodes) $node
  359. }
  360. }
  361. }
  362. }
  363. add {
  364. foreach node $args {
  365. if { [info exists data($node)] } {
  366. if { [lsearch $data(selnodes) $node] == -1 } {
  367. lappend data(selnodes) $node
  368. }
  369. }
  370. }
  371. }
  372. remove {
  373. foreach node $args {
  374. if { [set idx [lsearch $data(selnodes) $node]] != -1 } {
  375. set data(selnodes) [lreplace $data(selnodes) $idx $idx]
  376. }
  377. }
  378. }
  379. clear {
  380. set data(selnodes) {}
  381. }
  382. get {
  383. return $data(selnodes)
  384. }
  385. default {
  386. return
  387. }
  388. }
  389. _redraw_idle $path 1
  390. }
  391. # ------------------------------------------------------------------------------
  392. # Command Tree::exists
  393. # ------------------------------------------------------------------------------
  394. proc Tree::exists { path node } {
  395. variable $path
  396. upvar 0 $path data
  397. return [info exists data($node)]
  398. }
  399. # ------------------------------------------------------------------------------
  400. # Command Tree::visible
  401. # ------------------------------------------------------------------------------
  402. proc Tree::visible { path node } {
  403. set idn [$path:cmd find withtag n:$node]
  404. return [llength $idn]
  405. }
  406. # ------------------------------------------------------------------------------
  407. # Command Tree::parent
  408. # ------------------------------------------------------------------------------
  409. proc Tree::parent { path node } {
  410. variable $path
  411. upvar 0 $path data
  412. if { ![info exists data($node)] } {
  413. return -code error "node \"$node\" does not exist"
  414. }
  415. return [lindex $data($node) 0]
  416. }
  417. # ------------------------------------------------------------------------------
  418. # Command Tree::index
  419. # ------------------------------------------------------------------------------
  420. proc Tree::index { path node } {
  421. variable $path
  422. upvar 0 $path data
  423. if { ![string compare $node "root"] || ![info exists data($node)] } {
  424. return -code error "node \"$node\" does not exist"
  425. }
  426. set parent [lindex $data($node) 0]
  427. return [expr {[lsearch $data($parent) $node] - 1}]
  428. }
  429. # ------------------------------------------------------------------------------
  430. # Command Tree::nodes
  431. # ------------------------------------------------------------------------------
  432. proc Tree::nodes { path node {first ""} {last ""} } {
  433. variable $path
  434. upvar 0 $path data
  435. if { ![info exists data($node)] } {
  436. return -code error "node \"$node\" does not exist"
  437. }
  438. if { ![string length $first] } {
  439. return [lrange $data($node) 1 end]
  440. }
  441. if { ![string length $last] } {
  442. return [lindex [lrange $data($node) 1 end] $first]
  443. } else {
  444. return [lrange [lrange $data($node) 1 end] $first $last]
  445. }
  446. }
  447. # ------------------------------------------------------------------------------
  448. # Command Tree::see
  449. # ------------------------------------------------------------------------------
  450. proc Tree::see { path node } {
  451. variable $path
  452. upvar 0 $path data
  453. if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
  454. after cancel $data(upd,afterid)
  455. _redraw_tree $path
  456. }
  457. set idn [$path:cmd find withtag n:$node]
  458. if { $idn != "" } {
  459. Tree::_see $path $idn right
  460. Tree::_see $path $idn left
  461. }
  462. }
  463. # ------------------------------------------------------------------------------
  464. # Command Tree::opentree
  465. # ------------------------------------------------------------------------------
  466. proc Tree::opentree { path node } {
  467. variable $path
  468. upvar 0 $path data
  469. if { ![string compare $node "root"] || ![info exists data($node)] } {
  470. return -code error "node \"$node\" does not exist"
  471. }
  472. _recexpand $path $node 1 [Widget::getoption $path -opencmd]
  473. _redraw_idle $path 3
  474. }
  475. # ------------------------------------------------------------------------------
  476. # Command Tree::closetree
  477. # ------------------------------------------------------------------------------
  478. proc Tree::closetree { path node } {
  479. variable $path
  480. upvar 0 $path data
  481. if { ![string compare $node "root"] || ![info exists data($node)] } {
  482. return -code error "node \"$node\" does not exist"
  483. }
  484. _recexpand $path $node 0 [Widget::getoption $path -closecmd]
  485. _redraw_idle $path 3
  486. }
  487. # ------------------------------------------------------------------------------
  488. # Command Tree::edit
  489. # ------------------------------------------------------------------------------
  490. proc Tree::edit { path node text {verifycmd ""} {clickres 0} {select 1}} {
  491. variable _edit
  492. variable $path
  493. upvar 0 $path data
  494. if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
  495. after cancel $data(upd,afterid)
  496. _redraw_tree $path
  497. }
  498. set idn [$path:cmd find withtag n:$node]
  499. if { $idn != "" } {
  500. Tree::_see $path $idn right
  501. Tree::_see $path $idn left
  502. set oldfg [$path:cmd itemcget $idn -fill]
  503. set sbg [Widget::getoption $path -selectbackground]
  504. set coords [$path:cmd coords $idn]
  505. set x [lindex $coords 0]
  506. set y [lindex $coords 1]
  507. set bd [expr {[$path:cmd cget -borderwidth]+[$path:cmd cget -highlightthickness]}]
  508. set w [expr {[winfo width $path] - 2*$bd}]
  509. set wmax [expr {[$path:cmd canvasx $w]-$x}]
  510. set _edit(text) $text
  511. set _edit(wait) 0
  512. $path:cmd itemconfigure $idn -fill [Widget::getoption $path -background]
  513. $path:cmd itemconfigure s:$node -fill {} -outline {}
  514. set frame [frame $path.edit \
  515. -relief flat -borderwidth 0 -highlightthickness 0 \
  516. -background [Widget::getoption $path -background]]
  517. set ent [entry $frame.edit \
  518. -width 0 \
  519. -relief solid \
  520. -borderwidth 1 \
  521. -highlightthickness 0 \
  522. -foreground [Widget::getoption $path.$node -fill] \
  523. -background [Widget::getoption $path -background] \
  524. -selectforeground [Widget::getoption $path -selectforeground] \
  525. -selectbackground $sbg \
  526. -font [Widget::getoption $path.$node -font] \
  527. -textvariable Tree::_edit(text)]
  528. pack $ent -ipadx 8 -anchor w
  529. set idw [$path:cmd create window $x $y -window $frame -anchor w]
  530. trace variable Tree::_edit(text) w "Tree::_update_edit_size $path $ent $idw $wmax"
  531. tkwait visibility $ent
  532. grab $frame
  533. BWidget::focus set $ent
  534. _update_edit_size $path $ent $idw $wmax
  535. update
  536. if { $select } {
  537. $ent selection range 0 end
  538. $ent icursor end
  539. $ent xview end
  540. }
  541. bind $ent <Escape> {set Tree::_edit(wait) 0}
  542. bind $ent <Return> {set Tree::_edit(wait) 1}
  543. if { $clickres == 0 || $clickres == 1 } {
  544. bind $frame <Button> "set Tree::_edit(wait) $clickres"
  545. }
  546. set ok 0
  547. while { !$ok } {
  548. tkwait variable Tree::_edit(wait)
  549. if { !$_edit(wait) || $verifycmd == "" ||
  550. [uplevel \#0 $verifycmd [list $_edit(text)]] } {
  551. set ok 1
  552. }
  553. }
  554. trace vdelete Tree::_edit(text) w "Tree::_update_edit_size $path $ent $idw $wmax"
  555. grab release $frame
  556. BWidget::focus release $ent
  557. destroy $frame
  558. $path:cmd delete $idw
  559. $path:cmd itemconfigure $idn -fill $oldfg
  560. $path:cmd itemconfigure s:$node -fill $sbg -outline $sbg
  561. if { $_edit(wait) } {
  562. return $_edit(text)
  563. }
  564. }
  565. return ""
  566. }
  567. # ------------------------------------------------------------------------------
  568. # Command Tree::xview
  569. # ------------------------------------------------------------------------------
  570. proc Tree::xview { path args } {
  571. return [eval $path:cmd xview $args]
  572. }
  573. # ------------------------------------------------------------------------------
  574. # Command Tree::yview
  575. # ------------------------------------------------------------------------------
  576. proc Tree::yview { path args } {
  577. return [eval $path:cmd yview $args]
  578. }
  579. # ------------------------------------------------------------------------------
  580. # Command Tree::_update_edit_size
  581. # ------------------------------------------------------------------------------
  582. proc Tree::_update_edit_size { path entry idw wmax args } {
  583. set entw [winfo reqwidth $entry]
  584. if { $entw+8 >= $wmax } {
  585. $path:cmd itemconfigure $idw -width $wmax
  586. } else {
  587. $path:cmd itemconfigure $idw -width 0
  588. }
  589. }
  590. # ------------------------------------------------------------------------------
  591. # Command Tree::_destroy
  592. # ------------------------------------------------------------------------------
  593. proc Tree::_destroy { path } {
  594. variable $path
  595. upvar 0 $path data
  596. if { $data(upd,afterid) != "" } {
  597. after cancel $data(upd,afterid)
  598. }
  599. if { $data(dnd,afterid) != "" } {
  600. after cancel $data(dnd,afterid)
  601. }
  602. _subdelete $path [lrange $data(root) 1 end]
  603. Widget::destroy $path
  604. unset data
  605. rename $path {}
  606. }
  607. # ------------------------------------------------------------------------------
  608. # Command Tree::_see
  609. # ------------------------------------------------------------------------------
  610. proc Tree::_see { path idn side } {
  611. set bbox [$path:cmd bbox $idn]
  612. set scrl [$path:cmd cget -scrollregion]
  613. set ymax [lindex $scrl 3]
  614. set dy [$path:cmd cget -yscrollincrement]
  615. set yv [$path yview]
  616. set yv0 [expr {round([lindex $yv 0]*$ymax/$dy)}]
  617. set yv1 [expr {round([lindex $yv 1]*$ymax/$dy)}]
  618. set y [expr {int([lindex [$path:cmd coords $idn] 1]/$dy)}]
  619. if { $y < $yv0 } {
  620. $path:cmd yview scroll [expr {$y-$yv0}] units
  621. } elseif { $y >= $yv1 } {
  622. $path:cmd yview scroll [expr {$y-$yv1+1}] units
  623. }
  624. set xmax [lindex $scrl 2]
  625. set dx [$path:cmd cget -xscrollincrement]
  626. set xv [$path xview]
  627. if { ![string compare $side "right"] } {
  628. set xv1 [expr {round([lindex $xv 1]*$xmax/$dx)}]
  629. set x1 [expr {int([lindex $bbox 2]/$dx)}]
  630. if { $x1 >= $xv1 } {
  631. $path:cmd xview scroll [expr {$x1-$xv1+1}] units
  632. }
  633. } else {
  634. set xv0 [expr {round([lindex $xv 0]*$xmax/$dx)}]
  635. set x0 [expr {int([lindex $bbox 0]/$dx)}]
  636. if { $x0 < $xv0 } {
  637. $path:cmd xview scroll [expr {$x0-$xv0}] units
  638. }
  639. }
  640. }
  641. # ------------------------------------------------------------------------------
  642. # Command Tree::_recexpand
  643. # ------------------------------------------------------------------------------
  644. proc Tree::_recexpand { path node expand cmd } {
  645. variable $path
  646. upvar 0 $path data
  647. if { [Widget::getoption $path.$node -open] != $expand } {
  648. Widget::setoption $path.$node -open $expand
  649. if { $cmd != "" } {
  650. uplevel \#0 $cmd $node
  651. }
  652. }
  653. foreach subnode [lrange $data($node) 1 end] {
  654. _recexpand $path $subnode $expand $cmd
  655. }
  656. }
  657. # ------------------------------------------------------------------------------
  658. # Command Tree::_subdelete
  659. # ------------------------------------------------------------------------------
  660. proc Tree::_subdelete { path lnodes } {
  661. variable $path
  662. upvar 0 $path data
  663. while { [llength $lnodes] } {
  664. set lsubnodes [list]
  665. foreach node $lnodes {
  666. foreach subnode [lrange $data($node) 1 end] {
  667. lappend lsubnodes $subnode
  668. }
  669. unset data($node)
  670. if { [set win [Widget::getoption $path.$node -window]] != "" } {
  671. destroy $win
  672. }
  673. Widget::destroy $path.$node
  674. }
  675. set lnodes $lsubnodes
  676. }
  677. }
  678. # ------------------------------------------------------------------------------
  679. # Command Tree::_update_scrollregion
  680. # ------------------------------------------------------------------------------
  681. proc Tree::_update_scrollregion { path } {
  682. set bd [expr {2*([$path:cmd cget -borderwidth]+[$path:cmd cget -highlightthickness])}]
  683. set w [expr {[winfo width $path] - $bd}]
  684. set h [expr {[winfo height $path] - $bd}]
  685. set xinc [$path:cmd cget -xscrollincrement]
  686. set yinc [$path:cmd cget -yscrollincrement]
  687. set bbox [$path:cmd bbox all]
  688. if { [llength $bbox] } {
  689. set xs [lindex $bbox 2]
  690. set ys [lindex $bbox 3]
  691. if { $w < $xs } {
  692. set w [expr {int($xs)}]
  693. if { [set r [expr {$w % $xinc}]] } {
  694. set w [expr {$w+$xinc-$r}]
  695. }
  696. }
  697. if { $h < $ys } {
  698. set h [expr {int($ys)}]
  699. if { [set r [expr {$h % $yinc}]] } {
  700. set h [expr {$h+$yinc-$r}]
  701. }
  702. }
  703. }
  704. $path:cmd configure -scrollregion [list 0 0 $w $h]
  705. }
  706. # ------------------------------------------------------------------------------
  707. # Command Tree::_cross_event
  708. # ------------------------------------------------------------------------------
  709. proc Tree::_cross_event { path } {
  710. variable $path
  711. upvar 0 $path data
  712. set node [string range [lindex [$path:cmd gettags current] 1] 2 end]
  713. if { [Widget::getoption $path.$node -open] } {
  714. if { [set cmd [Widget::getoption $path -closecmd]] != "" } {
  715. uplevel \#0 $cmd $node
  716. }
  717. Widget::setoption $path.$node -open 0
  718. } else {
  719. if { [set cmd [Widget::getoption $path -opencmd]] != "" } {
  720. uplevel \#0 $cmd $node
  721. }
  722. Widget::setoption $path.$node -open 1
  723. }
  724. _redraw_idle $path 3
  725. }
  726. # ------------------------------------------------------------------------------
  727. # Command Tree::_draw_node
  728. # ------------------------------------------------------------------------------
  729. proc Tree::_draw_node { path node x0 y0 deltax deltay padx showlines } {
  730. global env
  731. variable $path
  732. upvar 0 $path data
  733. set x1 [expr {$x0+$deltax+5}]
  734. set y1 $y0
  735. if { $showlines } {
  736. $path:cmd create line $x0 $y0 $x1 $y0 \
  737. -fill [Widget::getoption $path -linesfill] \
  738. -stipple [Widget::getoption $path -linestipple] \
  739. -tags line
  740. }
  741. $path:cmd create text [expr {$x1+$padx}] $y0 \
  742. -text [Widget::getoption $path.$node -text] \
  743. -fill [Widget::getoption $path.$node -fill] \
  744. -font [Widget::getoption $path.$node -font] \
  745. -anchor w \
  746. -tags "node n:$node"
  747. set len [expr {[llength $data($node)] > 1}]
  748. set dc [Widget::getoption $path.$node -drawcross]
  749. set exp [Widget::getoption $path.$node -open]
  750. if { $len && $exp } {
  751. set y1 [_draw_subnodes $path [lrange $data($node) 1 end] \
  752. [expr {$x0+$deltax}] $y0 $deltax $deltay $padx $showlines]
  753. }
  754. if { [string compare $dc "never"] && ($len || ![string compare $dc "allways"]) } {
  755. if { $exp } {
  756. set bmp [file join $env(BWIDGET_LIBRARY) "images" "minus.xbm"]
  757. } else {
  758. set bmp [file join $env(BWIDGET_LIBRARY) "images" "plus.xbm"]
  759. }
  760. $path:cmd create bitmap $x0 $y0 \
  761. -bitmap @$bmp \
  762. -background [$path:cmd cget -background] \
  763. -foreground [Widget::getoption $path -linesfill] \
  764. -tags "cross c:$node" -anchor c
  765. }
  766. if { [set win [Widget::getoption $path.$node -window]] != "" } {
  767. $path:cmd create window $x1 $y0 -window $win -anchor w -tags "win i:$node"
  768. } elseif { [set img [Widget::getoption $path.$node -image]] != "" } {
  769. $path:cmd create image $x1 $y0 -image $img -anchor w -tags "img i:$node"
  770. }
  771. return $y1
  772. }
  773. # ------------------------------------------------------------------------------
  774. # Command Tree::_draw_subnodes
  775. # ------------------------------------------------------------------------------
  776. proc Tree::_draw_subnodes { path nodes x0 y0 deltax deltay padx showlines } {
  777. set y1 $y0
  778. foreach node $nodes {
  779. set yp $y1
  780. set y1 [_draw_node $path $node $x0 [expr {$y1+$deltay}] $deltax $deltay $padx $showlines]
  781. }
  782. if { $showlines && [llength $nodes] } {
  783. set id [$path:cmd create line $x0 $y0 $x0 [expr {$yp+$deltay}] \
  784. -fill [Widget::getoption $path -linesfill] \
  785. -stipple [Widget::getoption $path -linestipple] \
  786. -tags line]
  787. $path:cmd lower $id
  788. }
  789. return $y1
  790. }
  791. # ------------------------------------------------------------------------------
  792. # Command Tree::_update_nodes
  793. # ------------------------------------------------------------------------------
  794. proc Tree::_update_nodes { path } {
  795. global env
  796. variable $path
  797. upvar 0 $path data
  798. set deltax [Widget::getoption $path -deltax]
  799. set padx [Widget::getoption $path -padx]
  800. foreach {node flag} $data(upd,nodes) {
  801. set idn [$path:cmd find withtag "n:$node"]
  802. if { $idn == "" } {
  803. continue
  804. }
  805. set c [$path:cmd coords $idn]
  806. set x0 [expr {[lindex $c 0]-$padx}]
  807. set y0 [lindex $c 1]
  808. if { $flag & 48 } {
  809. # -window or -image modified
  810. set win [Widget::getoption $path.$node -window]
  811. set img [Widget::getoption $path.$node -image]
  812. set idi [$path:cmd find withtag i:$node]
  813. set type [lindex [$path:cmd gettags $idi] 0]
  814. if { [string length $win] } {
  815. if { ![string compare $type "win"] } {
  816. $path:cmd itemconfigure $idi -window $win
  817. } else {
  818. $path:cmd delete $idi
  819. $path:cmd create window $x0 $y0 -window $win -anchor w -tags "win i:$node"
  820. }
  821. } elseif { [string length $img] } {
  822. if { ![string compare $type "img"] } {
  823. $path:cmd itemconfigure $idi -image $img
  824. } else {
  825. $path:cmd delete $idi
  826. $path:cmd create image $x0 $y0 -image $img -anchor w -tags "img i:$node"
  827. }
  828. } else {
  829. $path:cmd delete $idi
  830. }
  831. }
  832. if { $flag & 8 } {
  833. # -drawcross modified
  834. set len [expr {[llength $data($node)] > 1}]
  835. set dc [Widget::getoption $path.$node -drawcross]
  836. set exp [Widget::getoption $path.$node -open]
  837. set idc [$path:cmd find withtag c:$node]
  838. if { [string compare $dc "never"] && ($len || ![string compare $dc "allways"]) } {
  839. if { $exp } {
  840. set bmp [file join $env(BWIDGET_LIBRARY) "images" "minus.xbm"]
  841. } else {
  842. set bmp [file join $env(BWIDGET_LIBRARY) "images" "plus.xbm"]
  843. }
  844. if { $idc == "" } {
  845. $path:cmd create bitmap [expr {$x0-$deltax-5}] $y0 \
  846. -bitmap @$bmp \
  847. -background [$path:cmd cget -background] \
  848. -foreground [Widget::getoption $path -linesfill] \
  849. -tags "cross c:$node" -anchor c
  850. } else {
  851. $path:cmd itemconfigure $idc -bitmap @$bmp
  852. }
  853. } else {
  854. $path:cmd delete $idc
  855. }
  856. }
  857. if { $flag & 7 } {
  858. # -font, -text or -fill modified
  859. $path:cmd itemconfigure $idn \
  860. -text [Widget::getoption $path.$node -text] \
  861. -fill [Widget::getoption $path.$node -fill] \
  862. -font [Widget::getoption $path.$node -font]
  863. }
  864. }
  865. }
  866. # ------------------------------------------------------------------------------
  867. # Command Tree::_draw_tree
  868. # ------------------------------------------------------------------------------
  869. proc Tree::_draw_tree { path } {
  870. variable $path
  871. upvar 0 $path data
  872. $path:cmd delete all
  873. $path:cmd configure -cursor watch
  874. _draw_subnodes $path [lrange $data(root) 1 end] 8 \
  875. [expr {-[Widget::getoption $path -deltay]/2}] \
  876. [Widget::getoption $path -deltax] \
  877. [Widget::getoption $path -deltay] \
  878. [Widget::getoption $path -padx] \
  879. [Widget::getoption $path -showlines]
  880. $path:cmd configure -cursor [Widget::getoption $path -cursor]
  881. }
  882. # ------------------------------------------------------------------------------
  883. # Command Tree::_redraw_tree
  884. # ------------------------------------------------------------------------------
  885. proc Tree::_redraw_tree { path } {
  886. variable $path
  887. upvar 0 $path data
  888. if { [Widget::getoption $path -redraw] } {
  889. if { $data(upd,level) == 2 } {
  890. _update_nodes $path
  891. } elseif { $data(upd,level) == 3 } {
  892. _draw_tree $path
  893. }
  894. _redraw_selection $path
  895. _update_scrollregion $path
  896. set data(upd,nodes) {}
  897. set data(upd,level) 0
  898. set data(upd,afterid) ""
  899. }
  900. }
  901. # ------------------------------------------------------------------------------
  902. # Command Tree::_redraw_selection
  903. # ------------------------------------------------------------------------------
  904. proc Tree::_redraw_selection { path } {
  905. variable $path
  906. upvar 0 $path data
  907. set selbg [Widget::getoption $path -selectbackground]
  908. set selfg [Widget::getoption $path -selectforeground]
  909. foreach id [$path:cmd find withtag sel] {
  910. set node [string range [lindex [$path:cmd gettags $id] 1] 2 end]
  911. $path:cmd itemconfigure "n:$node" -fill [Widget::getoption $path.$node -fill]
  912. }
  913. $path:cmd delete sel
  914. foreach node $data(selnodes) {
  915. set bbox [$path:cmd bbox "n:$node"]
  916. if { [llength $bbox] } {
  917. set id [eval $path:cmd create rectangle $bbox -fill $selbg -outline $selbg -tags [list "sel s:$node"]]
  918. $path:cmd itemconfigure "n:$node" -fill $selfg
  919. $path:cmd lower $id
  920. }
  921. }
  922. }
  923. # ------------------------------------------------------------------------------
  924. # Command Tree::_redraw_idle
  925. # ------------------------------------------------------------------------------
  926. proc Tree::_redraw_idle { path level } {
  927. variable $path
  928. upvar 0 $path data
  929. if { [Widget::getoption $path -redraw] && $data(upd,afterid) == "" } {
  930. set data(upd,afterid) [after idle Tree::_redraw_tree $path]
  931. }
  932. if { $level > $data(upd,level) } {
  933. set data(upd,level) $level
  934. }
  935. return ""
  936. }
  937. # --------------------------------------------------------------------------------------------
  938. # Commandes pour le Drag and Drop
  939. # ------------------------------------------------------------------------------
  940. # Command Tree::_init_drag_cmd
  941. # ------------------------------------------------------------------------------
  942. proc Tree::_init_drag_cmd { path X Y top } {
  943. set ltags [$path:cmd gettags current]
  944. set item [lindex $ltags 0]
  945. if { ![string compare $item "node"] ||
  946. ![string compare $item "img"] ||
  947. ![string compare $item "win"] } {
  948. set node [string range [lindex $ltags 1] 2 end]
  949. if { [set cmd [Widget::getoption $path -draginitcmd]] != "" } {
  950. return [uplevel \#0 $cmd [list $path $node $top]]
  951. }
  952. if { [set type [Widget::getoption $path -dragtype]] == "" } {
  953. set type "TREE_NODE"
  954. }
  955. if { [set img [Widget::getoption $path.$node -image]] != "" } {
  956. pack [label $top.l -image $img -padx 0 -pady 0]
  957. }
  958. return [list $type {copy move link} $node]
  959. }
  960. return {}
  961. }
  962. # ------------------------------------------------------------------------------
  963. # Command Tree::_drop_cmd
  964. # ------------------------------------------------------------------------------
  965. proc Tree::_drop_cmd { path source X Y op type dnddata } {
  966. variable $path
  967. upvar 0 $path data
  968. $path:cmd delete drop
  969. if { [string length $data(dnd,afterid)] } {
  970. after cancel $data(dnd,afterid)
  971. set data(dnd,afterid) ""
  972. }
  973. set data(dnd,scroll) ""
  974. if { [llength $data(dnd,node)] } {
  975. if { [set cmd [Widget::getoption $path -dropcmd]] != "" } {
  976. return [uplevel \#0 $cmd [list $path $source $data(dnd,node) $op $type $dnddata]]
  977. }
  978. }
  979. return 0
  980. }
  981. # ------------------------------------------------------------------------------
  982. # Command Tree::_over_cmd
  983. # ------------------------------------------------------------------------------
  984. proc Tree::_over_cmd { path source event X Y op type dnddata } {
  985. variable $path
  986. upvar 0 $path data
  987. if { ![string compare $event "leave"] } {
  988. # we leave the window tree
  989. $path:cmd delete drop
  990. if { [string length $data(dnd,afterid)] } {
  991. after cancel $data(dnd,afterid)
  992. set data(dnd,afterid) ""
  993. }
  994. set data(dnd,scroll) ""
  995. return 0
  996. }
  997. if { ![string compare $event "enter"] } {
  998. # we enter the window tree - dnd data initialization
  999. set mode [Widget::getoption $path -dropovermode]
  1000. set data(dnd,mode) 0
  1001. foreach c {w p n} {
  1002. set data(dnd,mode) [expr {($data(dnd,mode) << 1) | ([string first $c $mode] != -1)}]
  1003. }
  1004. set bbox [$path:cmd bbox all]
  1005. if { [llength $bbox] } {
  1006. set data(dnd,xs) [lindex $bbox 2]
  1007. } else {
  1008. set data(dnd,xs) 0
  1009. }
  1010. set data(dnd,node) {}
  1011. }
  1012. set x [expr {$X-[winfo rootx $path]}]
  1013. set y [expr {$Y-[winfo rooty $path]}]
  1014. $path:cmd delete drop
  1015. set data(dnd,node) {}
  1016. # test for auto-scroll unless mode is widget only
  1017. if { $data(dnd,mode) != 4 && [_auto_scroll $path $x $y] != "" } {
  1018. return 2
  1019. }
  1020. if { $data(dnd,mode) & 4 } {
  1021. # dropovermode includes widget
  1022. set target [list widget]
  1023. set vmode 4
  1024. } else {
  1025. set target [list ""]
  1026. set vmode 0
  1027. }
  1028. set xc [$path:cmd canvasx $x]
  1029. set xs $data(dnd,xs)
  1030. if { $xc <= $xs } {
  1031. set yc [$path:cmd canvasy $y]
  1032. set dy [$path:cmd cget -yscrollincrement]
  1033. set line [expr {int($yc/$dy)}]
  1034. set xi 0
  1035. set yi [expr {$line*$dy}]
  1036. set ys [expr {$yi+$dy}]
  1037. foreach id [$path:cmd find overlapping $xi $yi $xs $ys] {
  1038. set ltags [$path:cmd gettags $id]
  1039. set item [lindex $ltags 0]
  1040. if { ![string compare $item "node"] ||
  1041. ![string compare $item "img"] ||
  1042. ![string compare $item "win"] } {
  1043. # item is the label or image/window of the node
  1044. set node [string range [lindex $ltags 1] 2 end]
  1045. set xi [expr {[lindex [$path:cmd coords n:$node] 0]-[Widget::getoption $path -padx]}]
  1046. if { $data(dnd,mode) & 1 } {
  1047. # dropovermode includes node
  1048. lappend target $node
  1049. set vmode [expr {$vmode | 1}]
  1050. } else {
  1051. lappend target ""
  1052. }
  1053. if { $data(dnd,mode) & 2 } {
  1054. # dropovermode includes position
  1055. if { $yc >= $yi+$dy/2 } {
  1056. # position is after $node
  1057. if { [Widget::getoption $path.$node -open] &&
  1058. [llength $data($node)] > 1 } {
  1059. # $node is open and have subnodes
  1060. # drop position is 0 in children of $node
  1061. set parent $node
  1062. set index 0
  1063. set xli [expr {$xi-5}]
  1064. } else {
  1065. # $node is not open and doesn't have subnodes
  1066. # drop position is after $node in children of parent of $node
  1067. set parent [lindex $data($node) 0]
  1068. set index [lsearch $data($parent) $node]
  1069. set xli [expr {$xi-[Widget::getoption $path -deltax]-5}]
  1070. }
  1071. set yl $ys
  1072. } else {
  1073. # position is before $node
  1074. # drop position is before $node in children of parent of $node
  1075. set parent [lindex $data($node) 0]
  1076. set index [expr {[lsearch $data($parent) $node] - 1}]
  1077. set xli [expr {$xi-[Widget::getoption $path -deltax]-5}]
  1078. set yl $yi
  1079. }
  1080. lappend target [list $parent $index]
  1081. set vmode [expr {$vmode | 2}]
  1082. } else {
  1083. lappend target {}
  1084. }
  1085. if { ($vmode & 3) == 3 } {
  1086. # result have both node and position
  1087. # we compute what is the preferred method
  1088. if { $yc-$yi <= 3 || $ys-$yc <= 3 } {
  1089. lappend target "position"
  1090. } else {
  1091. lappend target "node"
  1092. }
  1093. }
  1094. break
  1095. }
  1096. }
  1097. }
  1098. if { $vmode && [set cmd [Widget::getoption $path -dropovercmd]] != "" } {
  1099. # user-defined dropover command
  1100. set res [uplevel \#0 $cmd [list $path $source $target $op $type $dnddata]]
  1101. set code [lindex $res 0]
  1102. set newmode 0
  1103. if { $code & 1 } {
  1104. # update vmode
  1105. set mode [lindex $res 1]
  1106. if { ($vmode & 1) && ![string compare $mode "node"] } {
  1107. set newmode 1
  1108. } elseif { ($vmode & 2) && ![string compare $mode "position"] } {
  1109. set newmode 2
  1110. } elseif { ($vmode & 4) && ![string compare $mode "widget"] } {
  1111. set newmode 4
  1112. }
  1113. }
  1114. set vmode $newmode
  1115. } else {
  1116. if { ($vmode & 3) == 3 } {
  1117. # result have both item and position
  1118. # we choose the preferred method
  1119. if { ![string compare [lindex $target 3] "position"] } {
  1120. set vmode [expr {$vmode & ~1}]
  1121. } else {
  1122. set vmode [expr {$vmode & ~2}]
  1123. }
  1124. }
  1125. if { $data(dnd,mode) == 4 || $data(dnd,mode) == 0 } {
  1126. # dropovermode is widget or empty - recall is not necessary
  1127. set code 1
  1128. } else {
  1129. set code 3
  1130. }
  1131. }
  1132. # draw dnd visual following vmode
  1133. if { $vmode & 1 } {
  1134. set data(dnd,node) [list "node" [lindex $target 1]]
  1135. $path:cmd create rectangle $xi $yi $xs $ys -tags drop
  1136. } elseif { $vmode & 2 } {
  1137. set data(dnd,node) [concat "position" [lindex $target 2]]
  1138. $path:cmd create line $xli [expr {$yl-$dy/2}] $xli $yl $xs $yl -tags drop
  1139. } elseif { $vmode & 4 } {
  1140. set data(dnd,node) [list "widget"]
  1141. } else {
  1142. set code [expr {$code & 2}]
  1143. }
  1144. if { $code & 1 } {
  1145. DropSite::setcursor based_arrow_down
  1146. } else {
  1147. DropSite::setcursor dot
  1148. }
  1149. return $code
  1150. }
  1151. # ------------------------------------------------------------------------------
  1152. # Command Tree::_auto_scroll
  1153. # ------------------------------------------------------------------------------
  1154. proc Tree::_auto_scroll { path x y } {
  1155. variable $path
  1156. upvar 0 $path data
  1157. set xmax [winfo width $path]
  1158. set ymax [winfo height $path]
  1159. set scroll {}
  1160. if { $y <= 6 } {
  1161. if { [lindex [$path:cmd yview] 0] > 0 } {
  1162. set scroll [list yview -1]
  1163. DropSite::setcursor sb_up_arrow
  1164. }
  1165. } elseif { $y >= $ymax-6 } {
  1166. if { [lindex [$path:cmd yview] 1] < 1 } {
  1167. set scroll [list yview 1]
  1168. DropSite::setcursor sb_down_arrow
  1169. }
  1170. } elseif { $x <= 6 } {
  1171. if { [lindex [$path:cmd xview] 0] > 0 } {
  1172. set scroll [list xview -1]
  1173. DropSite::setcursor sb_left_arrow
  1174. }
  1175. } elseif { $x >= $xmax-6 } {
  1176. if { [lindex [$path:cmd xview] 1] < 1 } {
  1177. set scroll [list xview 1]
  1178. DropSite::setcursor sb_right_arrow
  1179. }
  1180. }
  1181. if { [string length $data(dnd,afterid)] && [string compare $data(dnd,scroll) $scroll] } {
  1182. after cancel $data(dnd,afterid)
  1183. set data(dnd,afterid) ""
  1184. }
  1185. set data(dnd,scroll) $scroll
  1186. if { [string length $scroll] && ![string length $data(dnd,afterid)] } {
  1187. set data(dnd,afterid) [after 200 Tree::_scroll $path $scroll]
  1188. }
  1189. return $data(dnd,afterid)
  1190. }
  1191. # ------------------------------------------------------------------------------
  1192. # Command Tree::_scroll
  1193. # ------------------------------------------------------------------------------
  1194. proc Tree::_scroll { path cmd dir } {
  1195. variable $path
  1196. upvar 0 $path data
  1197. if { ($dir == -1 && [lindex [$path:cmd $cmd] 0] > 0) ||
  1198. ($dir == 1 && [lindex [$path:cmd $cmd] 1] < 1) } {
  1199. $path:cmd $cmd scroll $dir units
  1200. set data(dnd,afterid) [after 100 Tree::_scroll $path $cmd $dir]
  1201. } else {
  1202. set data(dnd,afterid) ""
  1203. DropSite::setcursor dot
  1204. }
  1205. }