PageRenderTime 57ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/02-development/uDrawGraph-3.1/lib/BWidget-1.7.0/tree.tcl

https://bitbucket.org/jmelo_lyncode/thesis
TCL | 2206 lines | 1547 code | 264 blank | 395 comment | 349 complexity | ee76f10495def3fea4f0d8a437bd0e84 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. # ----------------------------------------------------------------------------
  2. # tree.tcl
  3. # This file is part of Unifix BWidget Toolkit
  4. # $Id: tree.tcl,v 1.48 2003/10/20 21:23:53 damonc Exp $
  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. Widget::define Tree tree DragSite DropSite DynamicHelp
  51. namespace eval Node {
  52. Widget::declare Tree::Node {
  53. {-text String "" 0}
  54. {-font TkResource "" 0 listbox}
  55. {-image TkResource "" 0 label}
  56. {-window String "" 0}
  57. {-fill TkResource black 0 {listbox -foreground}}
  58. {-data String "" 0}
  59. {-open Boolean 0 0}
  60. {-selectable Boolean 1 0}
  61. {-drawcross Enum auto 0 {auto allways never}}
  62. {-padx Int -1 0 "%d >= -1"}
  63. {-deltax Int -1 0 "%d >= -1"}
  64. {-anchor String "w" 0 ""}
  65. }
  66. }
  67. DynamicHelp::include Tree::Node balloon
  68. Widget::tkinclude Tree canvas .c \
  69. remove {
  70. -insertwidth -insertbackground -insertborderwidth -insertofftime
  71. -insertontime -selectborderwidth -closeenough -confine -scrollregion
  72. -xscrollincrement -yscrollincrement -width -height
  73. } \
  74. initialize {
  75. -relief sunken -borderwidth 2 -takefocus 1
  76. -highlightthickness 1 -width 200
  77. }
  78. Widget::declare Tree {
  79. {-deltax Int 10 0 "%d >= 0"}
  80. {-deltay Int 15 0 "%d >= 0"}
  81. {-padx Int 20 0 "%d >= 0"}
  82. {-background TkResource "" 0 listbox}
  83. {-selectbackground TkResource "" 0 listbox}
  84. {-selectforeground TkResource "" 0 listbox}
  85. {-selectcommand String "" 0}
  86. {-width TkResource "" 0 listbox}
  87. {-height TkResource "" 0 listbox}
  88. {-selectfill Boolean 0 0}
  89. {-showlines Boolean 1 0}
  90. {-linesfill TkResource black 0 {listbox -foreground}}
  91. {-linestipple TkResource "" 0 {label -bitmap}}
  92. {-crossfill TkResource black 0 {listbox -foreground}}
  93. {-redraw Boolean 1 0}
  94. {-opencmd String "" 0}
  95. {-closecmd String "" 0}
  96. {-dropovermode Flag "wpn" 0 "wpn"}
  97. {-bg Synonym -background}
  98. {-crossopenimage String "" 0}
  99. {-crosscloseimage String "" 0}
  100. {-crossopenbitmap String "" 0}
  101. {-crossclosebitmap String "" 0}
  102. }
  103. DragSite::include Tree "TREE_NODE" 1
  104. DropSite::include Tree {
  105. TREE_NODE {copy {} move {}}
  106. }
  107. Widget::addmap Tree "" .c {-deltay -yscrollincrement}
  108. # Trees on windows have a white (system window) background
  109. if { $::tcl_platform(platform) == "windows" } {
  110. option add *Tree.c.background SystemWindow widgetDefault
  111. option add *TreeNode.fill SystemWindowText widgetDefault
  112. }
  113. bind Tree <FocusIn> [list after idle {BWidget::refocus %W %W.c}]
  114. bind Tree <Destroy> [list Tree::_destroy %W]
  115. bind Tree <Configure> [list Tree::_update_scrollregion %W]
  116. bind TreeSentinalStart <Button-1> {
  117. if { $::Tree::sentinal(%W) } {
  118. set ::Tree::sentinal(%W) 0
  119. break
  120. }
  121. }
  122. bind TreeSentinalEnd <Button-1> {
  123. set ::Tree::sentinal(%W) 0
  124. }
  125. bind TreeFocus <Button-1> [list focus %W]
  126. variable _edit
  127. }
  128. # ----------------------------------------------------------------------------
  129. # Command Tree::create
  130. # ----------------------------------------------------------------------------
  131. proc Tree::create { path args } {
  132. variable $path
  133. upvar 0 $path data
  134. Widget::init Tree $path $args
  135. set ::Tree::sentinal($path.c) 0
  136. if {[Widget::cget $path -crossopenbitmap] == ""} {
  137. set file [file join $::BWIDGET::LIBRARY images "minus.xbm"]
  138. Widget::configure $path [list -crossopenbitmap @$file]
  139. }
  140. if {[Widget::cget $path -crossclosebitmap] == ""} {
  141. set file [file join $::BWIDGET::LIBRARY images "plus.xbm"]
  142. Widget::configure $path [list -crossclosebitmap @$file]
  143. }
  144. set data(root) {{}}
  145. set data(selnodes) {}
  146. set data(upd,level) 0
  147. set data(upd,nodes) {}
  148. set data(upd,afterid) ""
  149. set data(dnd,scroll) ""
  150. set data(dnd,afterid) ""
  151. set data(dnd,selnodes) {}
  152. set data(dnd,node) ""
  153. frame $path -class Tree -bd 0 -highlightthickness 0 -relief flat \
  154. -takefocus 0
  155. # For 8.4+ we don't want to inherit the padding
  156. catch {$path configure -padx 0 -pady 0}
  157. eval [list canvas $path.c] [Widget::subcget $path .c] -xscrollincrement 8
  158. bindtags $path.c [list TreeSentinalStart TreeFocus $path.c Canvas \
  159. [winfo toplevel $path] all TreeSentinalEnd]
  160. pack $path.c -expand yes -fill both
  161. $path.c bind cross <ButtonPress-1> [list Tree::_cross_event $path]
  162. # Added by ericm@scriptics.com
  163. # These allow keyboard traversal of the tree
  164. bind $path.c <KeyPress-Up> [list Tree::_keynav up $path]
  165. bind $path.c <KeyPress-Down> [list Tree::_keynav down $path]
  166. bind $path.c <KeyPress-Right> [list Tree::_keynav right $path]
  167. bind $path.c <KeyPress-Left> [list Tree::_keynav left $path]
  168. bind $path.c <KeyPress-space> [list +Tree::_keynav space $path]
  169. # These allow keyboard control of the scrolling
  170. bind $path.c <Control-KeyPress-Up> [list $path.c yview scroll -1 units]
  171. bind $path.c <Control-KeyPress-Down> [list $path.c yview scroll 1 units]
  172. bind $path.c <Control-KeyPress-Left> [list $path.c xview scroll -1 units]
  173. bind $path.c <Control-KeyPress-Right> [list $path.c xview scroll 1 units]
  174. # ericm@scriptics.com
  175. BWidget::bindMouseWheel $path.c
  176. DragSite::setdrag $path $path.c Tree::_init_drag_cmd \
  177. [Widget::cget $path -dragendcmd] 1
  178. DropSite::setdrop $path $path.c Tree::_over_cmd Tree::_drop_cmd 1
  179. Widget::create Tree $path
  180. set w [Widget::cget $path -width]
  181. set h [Widget::cget $path -height]
  182. set dy [Widget::cget $path -deltay]
  183. $path.c configure -width [expr {$w*8}] -height [expr {$h*$dy}]
  184. # ericm
  185. # Bind <Button-1> to select the clicked node -- no reason not to, right?
  186. ## Bind button 1 to select the node via the _mouse_select command.
  187. ## This command will generate the proper <<TreeSelect>> virtual event
  188. ## when necessary.
  189. set selectcmd Tree::_mouse_select
  190. Tree::bindText $path <Button-1> [list $selectcmd $path set]
  191. Tree::bindImage $path <Button-1> [list $selectcmd $path set]
  192. Tree::bindText $path <Control-Button-1> [list $selectcmd $path toggle]
  193. Tree::bindImage $path <Control-Button-1> [list $selectcmd $path toggle]
  194. # Add sentinal bindings for double-clicking on items, to handle the
  195. # gnarly Tk bug wherein:
  196. # ButtonClick
  197. # ButtonClick
  198. # On a canvas item translates into button click on the item, button click
  199. # on the canvas, double-button on the item, single button click on the
  200. # canvas (which can happen if the double-button on the item causes some
  201. # other event to be handled in between when the button clicks are examined
  202. # for the canvas)
  203. $path.c bind TreeItemSentinal <Double-Button-1> \
  204. [list set ::Tree::sentinal($path.c) 1]
  205. # ericm
  206. return $path
  207. }
  208. # ----------------------------------------------------------------------------
  209. # Command Tree::configure
  210. # ----------------------------------------------------------------------------
  211. proc Tree::configure { path args } {
  212. variable $path
  213. upvar 0 $path data
  214. set res [Widget::configure $path $args]
  215. set ch1 [expr {[Widget::hasChanged $path -deltax val] |
  216. [Widget::hasChanged $path -deltay dy] |
  217. [Widget::hasChanged $path -padx val] |
  218. [Widget::hasChanged $path -showlines val]}]
  219. set ch2 [expr {[Widget::hasChanged $path -selectbackground val] |
  220. [Widget::hasChanged $path -selectforeground val]}]
  221. if { [Widget::hasChanged $path -linesfill fill] |
  222. [Widget::hasChanged $path -linestipple stipple] } {
  223. $path.c itemconfigure line -fill $fill -stipple $stipple
  224. }
  225. if { [Widget::hasChanged $path -crossfill fill] } {
  226. $path.c itemconfigure cross -foreground $fill
  227. }
  228. if {[Widget::hasChanged $path -selectfill fill]} {
  229. # Make sure that the full-width boxes have either all or none
  230. # of the standard node bindings
  231. if {$fill} {
  232. foreach event [$path.c bind "node"] {
  233. $path.c bind "box" $event [$path.c bind "node" $event]
  234. }
  235. } else {
  236. foreach event [$path.c bind "node"] {
  237. $path.c bind "box" $event {}
  238. }
  239. }
  240. }
  241. if { $ch1 } {
  242. _redraw_idle $path 3
  243. } elseif { $ch2 } {
  244. _redraw_idle $path 1
  245. }
  246. if { [Widget::hasChanged $path -height h] } {
  247. $path.c configure -height [expr {$h*$dy}]
  248. }
  249. if { [Widget::hasChanged $path -width w] } {
  250. $path.c configure -width [expr {$w*8}]
  251. }
  252. if { [Widget::hasChanged $path -redraw bool] && $bool } {
  253. set upd $data(upd,level)
  254. set data(upd,level) 0
  255. _redraw_idle $path $upd
  256. }
  257. set force [Widget::hasChanged $path -dragendcmd dragend]
  258. DragSite::setdrag $path $path.c Tree::_init_drag_cmd $dragend $force
  259. DropSite::setdrop $path $path.c Tree::_over_cmd Tree::_drop_cmd
  260. return $res
  261. }
  262. # ----------------------------------------------------------------------------
  263. # Command Tree::cget
  264. # ----------------------------------------------------------------------------
  265. proc Tree::cget { path option } {
  266. return [Widget::cget $path $option]
  267. }
  268. # ----------------------------------------------------------------------------
  269. # Command Tree::insert
  270. # ----------------------------------------------------------------------------
  271. proc Tree::insert { path index parent node args } {
  272. variable $path
  273. upvar 0 $path data
  274. set node [_node_name $path $node]
  275. set node [Widget::nextIndex $path $node]
  276. if { [info exists data($node)] } {
  277. return -code error "node \"$node\" already exists"
  278. }
  279. if { ![info exists data($parent)] } {
  280. return -code error "node \"$parent\" does not exist"
  281. }
  282. Widget::init Tree::Node $path.$node $args
  283. if {[string equal $index "end"]} {
  284. lappend data($parent) $node
  285. } else {
  286. incr index
  287. set data($parent) [linsert $data($parent) $index $node]
  288. }
  289. set data($node) [list $parent]
  290. if { [string equal $parent "root"] } {
  291. _redraw_idle $path 3
  292. } elseif { [visible $path $parent] } {
  293. # parent is visible...
  294. if { [Widget::getMegawidgetOption $path.$parent -open] } {
  295. # ...and opened -> redraw whole
  296. _redraw_idle $path 3
  297. } else {
  298. # ...and closed -> redraw cross
  299. lappend data(upd,nodes) $parent 8
  300. _redraw_idle $path 2
  301. }
  302. }
  303. return $node
  304. }
  305. # ----------------------------------------------------------------------------
  306. # Command Tree::itemconfigure
  307. # ----------------------------------------------------------------------------
  308. proc Tree::itemconfigure { path node args } {
  309. variable $path
  310. upvar 0 $path data
  311. set node [_node_name $path $node]
  312. if { [string equal $node "root"] || ![info exists data($node)] } {
  313. return -code error "node \"$node\" does not exist"
  314. }
  315. set result [Widget::configure $path.$node $args]
  316. _set_help $path $node
  317. if { [visible $path $node] } {
  318. set lopt {}
  319. set flag 0
  320. foreach opt {-window -image -drawcross -font -text -fill} {
  321. set flag [expr {$flag << 1}]
  322. if { [Widget::hasChanged $path.$node $opt val] } {
  323. set flag [expr {$flag | 1}]
  324. }
  325. }
  326. if { [Widget::hasChanged $path.$node -open val] } {
  327. if {[llength $data($node)] > 1} {
  328. # node have subnodes - full redraw
  329. _redraw_idle $path 3
  330. } else {
  331. # force a redraw of the plus/minus sign
  332. set flag [expr {$flag | 8}]
  333. }
  334. }
  335. if {$data(upd,level) < 3 && [Widget::hasChanged $path.$node -padx x]} {
  336. _redraw_idle $path 3
  337. }
  338. if { $data(upd,level) < 3 && $flag } {
  339. if { [set idx [lsearch -exact $data(upd,nodes) $node]] == -1 } {
  340. lappend data(upd,nodes) $node $flag
  341. } else {
  342. incr idx
  343. set flag [expr {[lindex $data(upd,nodes) $idx] | $flag}]
  344. set data(upd,nodes) [lreplace $data(upd,nodes) $idx $idx $flag]
  345. }
  346. _redraw_idle $path 2
  347. }
  348. }
  349. return $result
  350. }
  351. # ----------------------------------------------------------------------------
  352. # Command Tree::itemcget
  353. # ----------------------------------------------------------------------------
  354. proc Tree::itemcget { path node option } {
  355. # Instead of upvar'ing $path as data for this test, just directly refer to
  356. # it, as that is faster.
  357. set node [_node_name $path $node]
  358. if { [string equal $node "root"] || \
  359. ![info exists ::Tree::${path}($node)] } {
  360. return -code error "node \"$node\" does not exist"
  361. }
  362. return [Widget::cget $path.$node $option]
  363. }
  364. # ----------------------------------------------------------------------------
  365. # Command Tree::bindText
  366. # ----------------------------------------------------------------------------
  367. proc Tree::bindText { path event script } {
  368. if {[string length $script]} {
  369. append script " \[Tree::_get_node_name [list $path] current 2\]"
  370. }
  371. $path.c bind "node" $event $script
  372. if {[Widget::getoption $path -selectfill]} {
  373. $path.c bind "box" $event $script
  374. } else {
  375. $path.c bind "box" $event {}
  376. }
  377. }
  378. # ----------------------------------------------------------------------------
  379. # Command Tree::bindImage
  380. # ----------------------------------------------------------------------------
  381. proc Tree::bindImage { path event script } {
  382. if {[string length $script]} {
  383. append script " \[Tree::_get_node_name [list $path] current 2\]"
  384. }
  385. $path.c bind "img" $event $script
  386. if {[Widget::getoption $path -selectfill]} {
  387. $path.c bind "box" $event $script
  388. } else {
  389. $path.c bind "box" $event {}
  390. }
  391. }
  392. # ----------------------------------------------------------------------------
  393. # Command Tree::delete
  394. # ----------------------------------------------------------------------------
  395. proc Tree::delete { path args } {
  396. variable $path
  397. upvar 0 $path data
  398. foreach lnodes $args {
  399. foreach node $lnodes {
  400. set node [_node_name $path $node]
  401. if { ![string equal $node "root"] && [info exists data($node)] } {
  402. set parent [lindex $data($node) 0]
  403. set idx [lsearch -exact $data($parent) $node]
  404. set data($parent) [lreplace $data($parent) $idx $idx]
  405. _subdelete $path [list $node]
  406. }
  407. }
  408. }
  409. _redraw_idle $path 3
  410. }
  411. # ----------------------------------------------------------------------------
  412. # Command Tree::move
  413. # ----------------------------------------------------------------------------
  414. proc Tree::move { path parent node index } {
  415. variable $path
  416. upvar 0 $path data
  417. set node [_node_name $path $node]
  418. if { [string equal $node "root"] || ![info exists data($node)] } {
  419. return -code error "node \"$node\" does not exist"
  420. }
  421. if { ![info exists data($parent)] } {
  422. return -code error "node \"$parent\" does not exist"
  423. }
  424. set p $parent
  425. while { ![string equal $p "root"] } {
  426. if { [string equal $p $node] } {
  427. return -code error "node \"$parent\" is a descendant of \"$node\""
  428. }
  429. set p [parent $path $p]
  430. }
  431. set oldp [lindex $data($node) 0]
  432. set idx [lsearch -exact $data($oldp) $node]
  433. set data($oldp) [lreplace $data($oldp) $idx $idx]
  434. set data($node) [concat [list $parent] [lrange $data($node) 1 end]]
  435. if { [string equal $index "end"] } {
  436. lappend data($parent) $node
  437. } else {
  438. incr index
  439. set data($parent) [linsert $data($parent) $index $node]
  440. }
  441. if { ([string equal $oldp "root"] ||
  442. ([visible $path $oldp] && [Widget::getoption $path.$oldp -open])) ||
  443. ([string equal $parent "root"] ||
  444. ([visible $path $parent] && [Widget::getoption $path.$parent -open])) } {
  445. _redraw_idle $path 3
  446. }
  447. }
  448. # ----------------------------------------------------------------------------
  449. # Command Tree::reorder
  450. # ----------------------------------------------------------------------------
  451. proc Tree::reorder { path node neworder } {
  452. variable $path
  453. upvar 0 $path data
  454. set node [_node_name $path $node]
  455. if { ![info exists data($node)] } {
  456. return -code error "node \"$node\" does not exist"
  457. }
  458. set children [lrange $data($node) 1 end]
  459. if { [llength $children] } {
  460. set children [BWidget::lreorder $children $neworder]
  461. set data($node) [linsert $children 0 [lindex $data($node) 0]]
  462. if { [visible $path $node] && [Widget::getoption $path.$node -open] } {
  463. _redraw_idle $path 3
  464. }
  465. }
  466. }
  467. # ----------------------------------------------------------------------------
  468. # Command Tree::selection
  469. # ----------------------------------------------------------------------------
  470. proc Tree::selection { path cmd args } {
  471. variable $path
  472. upvar 0 $path data
  473. switch -- $cmd {
  474. toggle {
  475. foreach node $args {
  476. set node [_node_name $path $node]
  477. if {![info exists data($node)]} {
  478. return -code error \
  479. "$path selection toggle: Cannot toggle unknown node \"$node\"."
  480. }
  481. }
  482. foreach node $args {
  483. set node [_node_name $path $node]
  484. if {[$path selection includes $node]} {
  485. $path selection remove $node
  486. } else {
  487. $path selection add $node
  488. }
  489. }
  490. }
  491. set {
  492. foreach node $args {
  493. set node [_node_name $path $node]
  494. if {![info exists data($node)]} {
  495. return -code error \
  496. "$path selection set: Cannot select unknown node \"$node\"."
  497. }
  498. }
  499. set data(selnodes) {}
  500. foreach node $args {
  501. set node [_node_name $path $node]
  502. if { [Widget::getoption $path.$node -selectable] } {
  503. if { [lsearch -exact $data(selnodes) $node] == -1 } {
  504. lappend data(selnodes) $node
  505. }
  506. }
  507. }
  508. __call_selectcmd $path
  509. }
  510. add {
  511. foreach node $args {
  512. set node [_node_name $path $node]
  513. if {![info exists data($node)]} {
  514. return -code error \
  515. "$path selection add: Cannot select unknown node \"$node\"."
  516. }
  517. }
  518. foreach node $args {
  519. set node [_node_name $path $node]
  520. if { [Widget::getoption $path.$node -selectable] } {
  521. if { [lsearch -exact $data(selnodes) $node] == -1 } {
  522. lappend data(selnodes) $node
  523. }
  524. }
  525. }
  526. __call_selectcmd $path
  527. }
  528. range {
  529. # Here's our algorithm:
  530. # make a list of all nodes, then take the range from node1
  531. # to node2 and select those nodes
  532. #
  533. # This works because of how this widget handles redraws:
  534. # The tree is always completely redrawn, and always from
  535. # top to bottom. So the list of visible nodes *is* the
  536. # list of nodes, and we can use that to decide which nodes
  537. # to select.
  538. if {[llength $args] != 2} {
  539. return -code error \
  540. "wrong#args: Expected $path selection range node1 node2"
  541. }
  542. foreach {node1 node2} $args break
  543. set node1 [_node_name $path $node1]
  544. set node2 [_node_name $path $node2]
  545. if {![info exists data($node1)]} {
  546. return -code error \
  547. "$path selection range: Cannot start range at unknown node \"$node1\"."
  548. }
  549. if {![info exists data($node2)]} {
  550. return -code error \
  551. "$path selection range: Cannot end range at unknown node \"$node2\"."
  552. }
  553. set nodes {}
  554. foreach nodeItem [$path.c find withtag node] {
  555. set node [Tree::_get_node_name $path $nodeItem 2]
  556. if { [Widget::getoption $path.$node -selectable] } {
  557. lappend nodes $node
  558. }
  559. }
  560. # surles: Set the root string to the first element on the list.
  561. if {$node1 == "root"} {
  562. set node1 [lindex $nodes 0]
  563. }
  564. if {$node2 == "root"} {
  565. set node2 [lindex $nodes 0]
  566. }
  567. # Find the first visible ancestor of node1, starting with node1
  568. while {[set index1 [lsearch -exact $nodes $node1]] == -1} {
  569. set node1 [lindex $data($node1) 0]
  570. }
  571. # Find the first visible ancestor of node2, starting with node2
  572. while {[set index2 [lsearch -exact $nodes $node2]] == -1} {
  573. set node2 [lindex $data($node2) 0]
  574. }
  575. # If the nodes were given in backwards order, flip the
  576. # indices now
  577. if { $index2 < $index1 } {
  578. incr index1 $index2
  579. set index2 [expr {$index1 - $index2}]
  580. set index1 [expr {$index1 - $index2}]
  581. }
  582. set data(selnodes) [lrange $nodes $index1 $index2]
  583. __call_selectcmd $path
  584. }
  585. remove {
  586. foreach node $args {
  587. set node [_node_name $path $node]
  588. if { [set idx [lsearch -exact $data(selnodes) $node]] != -1 } {
  589. set data(selnodes) [lreplace $data(selnodes) $idx $idx]
  590. }
  591. }
  592. __call_selectcmd $path
  593. }
  594. clear {
  595. if {[llength $args] != 0} {
  596. return -code error \
  597. "wrong#args: Expected $path selection clear"
  598. }
  599. set data(selnodes) {}
  600. __call_selectcmd $path
  601. }
  602. get {
  603. if {[llength $args] != 0} {
  604. return -code error \
  605. "wrong#args: Expected $path selection get"
  606. }
  607. return $data(selnodes)
  608. }
  609. includes {
  610. if {[llength $args] != 1} {
  611. return -code error \
  612. "wrong#args: Expected $path selection includes node"
  613. }
  614. set node [lindex $args 0]
  615. set node [_node_name $path $node]
  616. return [expr {[lsearch -exact $data(selnodes) $node] != -1}]
  617. }
  618. default {
  619. return
  620. }
  621. }
  622. _redraw_idle $path 1
  623. }
  624. proc Tree::getcanvas { path } {
  625. return $path.c
  626. }
  627. proc Tree::__call_selectcmd { path } {
  628. variable $path
  629. upvar 0 $path data
  630. set selectcmd [Widget::getoption $path -selectcommand]
  631. if {[llength $selectcmd]} {
  632. lappend selectcmd $path
  633. lappend selectcmd $data(selnodes)
  634. uplevel \#0 $selectcmd
  635. }
  636. return
  637. }
  638. # ----------------------------------------------------------------------------
  639. # Command Tree::exists
  640. # ----------------------------------------------------------------------------
  641. proc Tree::exists { path node } {
  642. variable $path
  643. upvar 0 $path data
  644. set node [_node_name $path $node]
  645. return [info exists data($node)]
  646. }
  647. # ----------------------------------------------------------------------------
  648. # Command Tree::visible
  649. # ----------------------------------------------------------------------------
  650. proc Tree::visible { path node } {
  651. set node [_node_name $path $node]
  652. set idn [$path.c find withtag n:$node]
  653. return [llength $idn]
  654. }
  655. # ----------------------------------------------------------------------------
  656. # Command Tree::parent
  657. # ----------------------------------------------------------------------------
  658. proc Tree::parent { path node } {
  659. variable $path
  660. upvar 0 $path data
  661. set node [_node_name $path $node]
  662. if { ![info exists data($node)] } {
  663. return -code error "node \"$node\" does not exist"
  664. }
  665. return [lindex $data($node) 0]
  666. }
  667. # ----------------------------------------------------------------------------
  668. # Command Tree::index
  669. # ----------------------------------------------------------------------------
  670. proc Tree::index { path node } {
  671. variable $path
  672. upvar 0 $path data
  673. set node [_node_name $path $node]
  674. if { [string equal $node "root"] || ![info exists data($node)] } {
  675. return -code error "node \"$node\" does not exist"
  676. }
  677. set parent [lindex $data($node) 0]
  678. return [expr {[lsearch -exact $data($parent) $node] - 1}]
  679. }
  680. # ----------------------------------------------------------------------------
  681. # Tree::find
  682. # Returns the node given a position.
  683. # findInfo @x,y ?confine?
  684. # lineNumber
  685. # ----------------------------------------------------------------------------
  686. proc Tree::find {path findInfo {confine ""}} {
  687. if {[regexp -- {^@([0-9]+),([0-9]+)$} $findInfo match x y]} {
  688. set x [$path.c canvasx $x]
  689. set y [$path.c canvasy $y]
  690. } elseif {[regexp -- {^[0-9]+$} $findInfo lineNumber]} {
  691. set dy [Widget::getoption $path -deltay]
  692. set y [expr {$dy*($lineNumber+0.5)}]
  693. set confine ""
  694. } else {
  695. return -code error "invalid find spec \"$findInfo\""
  696. }
  697. set found 0
  698. set region [$path.c bbox all]
  699. if {[llength $region]} {
  700. set xi [lindex $region 0]
  701. set xs [lindex $region 2]
  702. foreach id [$path.c find overlapping $xi $y $xs $y] {
  703. set ltags [$path.c gettags $id]
  704. set item [lindex $ltags 1]
  705. if { [string equal $item "node"] ||
  706. [string equal $item "img"] ||
  707. [string equal $item "win"] } {
  708. # item is the label or image/window of the node
  709. set node [Tree::_get_node_name $path $id 2]
  710. set found 1
  711. break
  712. }
  713. }
  714. }
  715. if {$found} {
  716. if {[string equal $confine "confine"]} {
  717. # test if x stand inside node bbox
  718. set padx [_get_node_padx $path $node]
  719. set xi [expr {[lindex [$path.c coords n:$node] 0] - $padx}]
  720. set xs [lindex [$path.c bbox n:$node] 2]
  721. if {$x >= $xi && $x <= $xs} {
  722. return $node
  723. }
  724. } else {
  725. return $node
  726. }
  727. }
  728. return ""
  729. }
  730. # ----------------------------------------------------------------------------
  731. # Command Tree::line
  732. # Returns the line where is drawn a node.
  733. # ----------------------------------------------------------------------------
  734. proc Tree::line {path node} {
  735. set node [_node_name $path $node]
  736. set item [$path.c find withtag n:$node]
  737. if {[string length $item]} {
  738. set dy [Widget::getoption $path -deltay]
  739. set y [lindex [$path.c coords $item] 1]
  740. set line [expr {int($y/$dy)}]
  741. } else {
  742. set line -1
  743. }
  744. return $line
  745. }
  746. # ----------------------------------------------------------------------------
  747. # Command Tree::nodes
  748. # ----------------------------------------------------------------------------
  749. proc Tree::nodes { path node {first ""} {last ""} } {
  750. variable $path
  751. upvar 0 $path data
  752. set node [_node_name $path $node]
  753. if { ![info exists data($node)] } {
  754. return -code error "node \"$node\" does not exist"
  755. }
  756. if { ![string length $first] } {
  757. return [lrange $data($node) 1 end]
  758. }
  759. if { ![string length $last] } {
  760. return [lindex [lrange $data($node) 1 end] $first]
  761. } else {
  762. return [lrange [lrange $data($node) 1 end] $first $last]
  763. }
  764. }
  765. # Tree::visiblenodes --
  766. #
  767. # Retrieve a list of all the nodes in a tree.
  768. #
  769. # Arguments:
  770. # path tree to retrieve nodes for.
  771. #
  772. # Results:
  773. # nodes list of nodes in the tree.
  774. proc Tree::visiblenodes { path } {
  775. variable $path
  776. upvar 0 $path data
  777. # Root is always open (?), so all of its children automatically get added
  778. # to the result, and to the stack.
  779. set st [lrange $data(root) 1 end]
  780. set result $st
  781. while {[llength $st]} {
  782. set node [lindex $st end]
  783. set st [lreplace $st end end]
  784. # Danger, danger! Using getMegawidgetOption is fragile, but much
  785. # much faster than going through cget.
  786. if { [Widget::getMegawidgetOption $path.$node -open] } {
  787. set nodes [lrange $data($node) 1 end]
  788. set result [concat $result $nodes]
  789. set st [concat $st $nodes]
  790. }
  791. }
  792. return $result
  793. }
  794. # ----------------------------------------------------------------------------
  795. # Command Tree::see
  796. # ----------------------------------------------------------------------------
  797. proc Tree::see { path node } {
  798. variable $path
  799. upvar 0 $path data
  800. set node [_node_name $path $node]
  801. if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
  802. after cancel $data(upd,afterid)
  803. _redraw_tree $path
  804. }
  805. set idn [$path.c find withtag n:$node]
  806. if { $idn != "" } {
  807. Tree::_see $path $idn
  808. }
  809. }
  810. # ----------------------------------------------------------------------------
  811. # Command Tree::opentree
  812. # ----------------------------------------------------------------------------
  813. # JDC: added option recursive
  814. proc Tree::opentree { path node {recursive 1} } {
  815. variable $path
  816. upvar 0 $path data
  817. set node [_node_name $path $node]
  818. if { [string equal $node "root"] || ![info exists data($node)] } {
  819. return -code error "node \"$node\" does not exist"
  820. }
  821. _recexpand $path $node 1 $recursive [Widget::getoption $path -opencmd]
  822. _redraw_idle $path 3
  823. }
  824. # ----------------------------------------------------------------------------
  825. # Command Tree::closetree
  826. # ----------------------------------------------------------------------------
  827. proc Tree::closetree { path node {recursive 1} } {
  828. variable $path
  829. upvar 0 $path data
  830. set node [_node_name $path $node]
  831. if { [string equal $node "root"] || ![info exists data($node)] } {
  832. return -code error "node \"$node\" does not exist"
  833. }
  834. _recexpand $path $node 0 $recursive [Widget::getoption $path -closecmd]
  835. _redraw_idle $path 3
  836. }
  837. proc Tree::toggle { path node } {
  838. if {[$path itemcget $node -open]} {
  839. $path closetree $node 0
  840. } else {
  841. $path opentree $node 0
  842. }
  843. }
  844. # ----------------------------------------------------------------------------
  845. # Command Tree::edit
  846. # ----------------------------------------------------------------------------
  847. proc Tree::edit { path node text {verifycmd ""} {clickres 0} {select 1}} {
  848. variable _edit
  849. variable $path
  850. upvar 0 $path data
  851. set node [_node_name $path $node]
  852. if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
  853. after cancel $data(upd,afterid)
  854. _redraw_tree $path
  855. }
  856. set idn [$path.c find withtag n:$node]
  857. if { $idn != "" } {
  858. Tree::_see $path $idn
  859. set oldfg [$path.c itemcget $idn -fill]
  860. set sbg [Widget::getoption $path -selectbackground]
  861. set coords [$path.c coords $idn]
  862. set x [lindex $coords 0]
  863. set y [lindex $coords 1]
  864. set bd [expr {[$path.c cget -borderwidth]+[$path.c cget -highlightthickness]}]
  865. set w [expr {[winfo width $path] - 2*$bd}]
  866. set wmax [expr {[$path.c canvasx $w]-$x}]
  867. set _edit(text) $text
  868. set _edit(wait) 0
  869. $path.c itemconfigure $idn -fill [Widget::getoption $path -background]
  870. $path.c itemconfigure s:$node -fill {} -outline {}
  871. set frame [frame $path.edit \
  872. -relief flat -borderwidth 0 -highlightthickness 0 \
  873. -background [Widget::getoption $path -background]]
  874. set ent [entry $frame.edit \
  875. -width 0 \
  876. -relief solid \
  877. -borderwidth 1 \
  878. -highlightthickness 0 \
  879. -foreground [Widget::getoption $path.$node -fill] \
  880. -background [Widget::getoption $path -background] \
  881. -selectforeground [Widget::getoption $path -selectforeground] \
  882. -selectbackground $sbg \
  883. -font [Widget::getoption $path.$node -font] \
  884. -textvariable Tree::_edit(text)]
  885. pack $ent -ipadx 8 -anchor w
  886. set idw [$path.c create window $x $y -window $frame -anchor w]
  887. trace variable Tree::_edit(text) w \
  888. [list Tree::_update_edit_size $path $ent $idw $wmax]
  889. tkwait visibility $ent
  890. grab $frame
  891. BWidget::focus set $ent
  892. _update_edit_size $path $ent $idw $wmax
  893. update
  894. if { $select } {
  895. $ent selection range 0 end
  896. $ent icursor end
  897. $ent xview end
  898. }
  899. bindtags $ent [list $ent Entry]
  900. bind $ent <Escape> {set Tree::_edit(wait) 0}
  901. bind $ent <Return> {set Tree::_edit(wait) 1}
  902. if { $clickres == 0 || $clickres == 1 } {
  903. bind $frame <Button> [list set Tree::_edit(wait) $clickres]
  904. }
  905. set ok 0
  906. while { !$ok } {
  907. tkwait variable Tree::_edit(wait)
  908. if { !$_edit(wait) || $verifycmd == "" ||
  909. [uplevel \#0 $verifycmd [list $_edit(text)]] } {
  910. set ok 1
  911. }
  912. }
  913. trace vdelete Tree::_edit(text) w \
  914. [list Tree::_update_edit_size $path $ent $idw $wmax]
  915. grab release $frame
  916. BWidget::focus release $ent
  917. destroy $frame
  918. $path.c delete $idw
  919. $path.c itemconfigure $idn -fill $oldfg
  920. $path.c itemconfigure s:$node -fill $sbg -outline $sbg
  921. if { $_edit(wait) } {
  922. return $_edit(text)
  923. }
  924. }
  925. return ""
  926. }
  927. # ----------------------------------------------------------------------------
  928. # Command Tree::xview
  929. # ----------------------------------------------------------------------------
  930. proc Tree::xview { path args } {
  931. return [eval [list $path.c xview] $args]
  932. }
  933. # ----------------------------------------------------------------------------
  934. # Command Tree::yview
  935. # ----------------------------------------------------------------------------
  936. proc Tree::yview { path args } {
  937. return [eval [list $path.c yview] $args]
  938. }
  939. # ----------------------------------------------------------------------------
  940. # Command Tree::_update_edit_size
  941. # ----------------------------------------------------------------------------
  942. proc Tree::_update_edit_size { path entry idw wmax args } {
  943. set entw [winfo reqwidth $entry]
  944. if { $entw+8 >= $wmax } {
  945. $path.c itemconfigure $idw -width $wmax
  946. } else {
  947. $path.c itemconfigure $idw -width 0
  948. }
  949. }
  950. # ----------------------------------------------------------------------------
  951. # Command Tree::_see
  952. # ----------------------------------------------------------------------------
  953. proc Tree::_see { path idn } {
  954. set bbox [$path.c bbox $idn]
  955. set scrl [$path.c cget -scrollregion]
  956. set ymax [lindex $scrl 3]
  957. set dy [$path.c cget -yscrollincrement]
  958. set yv [$path yview]
  959. set yv0 [expr {round([lindex $yv 0]*$ymax/$dy)}]
  960. set yv1 [expr {round([lindex $yv 1]*$ymax/$dy)}]
  961. set y [expr {int([lindex [$path.c coords $idn] 1]/$dy)}]
  962. if { $y < $yv0 } {
  963. $path.c yview scroll [expr {$y-$yv0}] units
  964. } elseif { $y >= $yv1 } {
  965. $path.c yview scroll [expr {$y-$yv1+1}] units
  966. }
  967. set xmax [lindex $scrl 2]
  968. set dx [$path.c cget -xscrollincrement]
  969. set xv [$path xview]
  970. set x0 [expr {int([lindex $bbox 0]/$dx)}]
  971. set xv0 [expr {round([lindex $xv 0]*$xmax/$dx)}]
  972. set xv1 [expr {round([lindex $xv 1]*$xmax/$dx)}]
  973. if { $x0 >= $xv1 || $x0 < $xv0 } {
  974. $path.c xview scroll [expr {$x0-$xv0}] units
  975. }
  976. }
  977. # ----------------------------------------------------------------------------
  978. # Command Tree::_recexpand
  979. # ----------------------------------------------------------------------------
  980. # JDC : added option recursive
  981. proc Tree::_recexpand { path node expand recursive cmd } {
  982. variable $path
  983. upvar 0 $path data
  984. if { [Widget::getoption $path.$node -open] != $expand } {
  985. Widget::setoption $path.$node -open $expand
  986. if { $cmd != "" } {
  987. uplevel \#0 $cmd [list $node]
  988. }
  989. }
  990. if { $recursive } {
  991. foreach subnode [lrange $data($node) 1 end] {
  992. _recexpand $path $subnode $expand $recursive $cmd
  993. }
  994. }
  995. }
  996. # ----------------------------------------------------------------------------
  997. # Command Tree::_subdelete
  998. # ----------------------------------------------------------------------------
  999. proc Tree::_subdelete { path lnodes } {
  1000. variable $path
  1001. upvar 0 $path data
  1002. set sel $data(selnodes)
  1003. while { [llength $lnodes] } {
  1004. set lsubnodes [list]
  1005. foreach node $lnodes {
  1006. foreach subnode [lrange $data($node) 1 end] {
  1007. lappend lsubnodes $subnode
  1008. }
  1009. unset data($node)
  1010. set idx [lsearch -exact $sel $node]
  1011. if { $idx >= 0 } {
  1012. set sel [lreplace $sel $idx $idx]
  1013. }
  1014. if { [set win [Widget::getoption $path.$node -window]] != "" } {
  1015. destroy $win
  1016. }
  1017. Widget::destroy $path.$node
  1018. }
  1019. set lnodes $lsubnodes
  1020. }
  1021. set data(selnodes) $sel
  1022. }
  1023. # ----------------------------------------------------------------------------
  1024. # Command Tree::_update_scrollregion
  1025. # ----------------------------------------------------------------------------
  1026. proc Tree::_update_scrollregion { path } {
  1027. set bd [expr {2*([$path.c cget -borderwidth]+[$path.c cget -highlightthickness])}]
  1028. set w [expr {[winfo width $path] - $bd}]
  1029. set h [expr {[winfo height $path] - $bd}]
  1030. set xinc [$path.c cget -xscrollincrement]
  1031. set yinc [$path.c cget -yscrollincrement]
  1032. set bbox [$path.c bbox node]
  1033. if { [llength $bbox] } {
  1034. set xs [lindex $bbox 2]
  1035. set ys [lindex $bbox 3]
  1036. if { $w < $xs } {
  1037. set w [expr {int($xs)}]
  1038. if { [set r [expr {$w % $xinc}]] } {
  1039. set w [expr {$w+$xinc-$r}]
  1040. }
  1041. }
  1042. if { $h < $ys } {
  1043. set h [expr {int($ys)}]
  1044. if { [set r [expr {$h % $yinc}]] } {
  1045. set h [expr {$h+$yinc-$r}]
  1046. }
  1047. }
  1048. }
  1049. $path.c configure -scrollregion [list 0 0 $w $h]
  1050. if {[Widget::getoption $path -selectfill]} {
  1051. _redraw_selection $path
  1052. }
  1053. }
  1054. # ----------------------------------------------------------------------------
  1055. # Command Tree::_cross_event
  1056. # ----------------------------------------------------------------------------
  1057. proc Tree::_cross_event { path } {
  1058. variable $path
  1059. upvar 0 $path data
  1060. set node [Tree::_get_node_name $path current 1]
  1061. if { [Widget::getoption $path.$node -open] } {
  1062. Tree::itemconfigure $path $node -open 0
  1063. if { [set cmd [Widget::getoption $path -closecmd]] != "" } {
  1064. uplevel \#0 $cmd [list $node]
  1065. }
  1066. } else {
  1067. Tree::itemconfigure $path $node -open 1
  1068. if { [set cmd [Widget::getoption $path -opencmd]] != "" } {
  1069. uplevel \#0 $cmd [list $node]
  1070. }
  1071. }
  1072. }
  1073. proc Tree::_draw_cross { path node open x y } {
  1074. set idc [$path.c find withtag c:$node]
  1075. if { $open } {
  1076. set img [Widget::cget $path -crossopenimage]
  1077. set bmp [Widget::cget $path -crossopenbitmap]
  1078. } else {
  1079. set img [Widget::cget $path -crosscloseimage]
  1080. set bmp [Widget::cget $path -crossclosebitmap]
  1081. }
  1082. ## If we already have a cross for this node, we just adjust the image.
  1083. if {$idc != ""} {
  1084. if {$img == ""} {
  1085. $path.c itemconfigure $idc -bitmap $bmp
  1086. } else {
  1087. $path.c itemconfigure $idc -image $img
  1088. }
  1089. return
  1090. }
  1091. ## Create a new image for the cross. If the user has specified an
  1092. ## image, it overrides a bitmap.
  1093. if {$img == ""} {
  1094. $path.c create bitmap $x $y \
  1095. -bitmap $bmp \
  1096. -background [$path.c cget -background] \
  1097. -foreground [Widget::getoption $path -crossfill] \
  1098. -tags [list cross c:$node] -anchor c
  1099. } else {
  1100. $path.c create image $x $y \
  1101. -image $img \
  1102. -tags [list cross c:$node] -anchor c
  1103. }
  1104. }
  1105. # ----------------------------------------------------------------------------
  1106. # Command Tree::_draw_node
  1107. # ----------------------------------------------------------------------------
  1108. proc Tree::_draw_node { path node x0 y0 deltax deltay padx showlines } {
  1109. global env
  1110. variable $path
  1111. upvar 0 $path data
  1112. set x1 [expr {$x0+$deltax+5}]
  1113. set y1 $y0
  1114. if { $showlines } {
  1115. $path.c create line $x0 $y0 $x1 $y0 \
  1116. -fill [Widget::getoption $path -linesfill] \
  1117. -stipple [Widget::getoption $path -linestipple] \
  1118. -tags line
  1119. }
  1120. $path.c create text [expr {$x1+$padx}] $y0 \
  1121. -text [Widget::getoption $path.$node -text] \
  1122. -fill [Widget::getoption $path.$node -fill] \
  1123. -font [Widget::getoption $path.$node -font] \
  1124. -anchor w \
  1125. -tags [Tree::_get_node_tags $path $node [list node n:$node]]
  1126. set len [expr {[llength $data($node)] > 1}]
  1127. set dc [Widget::getoption $path.$node -drawcross]
  1128. set exp [Widget::getoption $path.$node -open]
  1129. if { $len && $exp } {
  1130. set y1 [_draw_subnodes $path [lrange $data($node) 1 end] \
  1131. [expr {$x0+$deltax}] $y0 $deltax $deltay $padx $showlines]
  1132. }
  1133. if {![string equal $dc "never"] && ($len || [string equal $dc "allways"])} {
  1134. _draw_cross $path $node $exp $x0 $y0
  1135. }
  1136. if { [set win [Widget::getoption $path.$node -window]] != "" } {
  1137. set a [Widget::cget $path.$node -anchor]
  1138. $path.c create window $x1 $y0 -window $win -anchor $a \
  1139. -tags [Tree::_get_node_tags $path $node [list win i:$node]]
  1140. } elseif { [set img [Widget::getoption $path.$node -image]] != "" } {
  1141. set a [Widget::cget $path.$node -anchor]
  1142. $path.c create image $x1 $y0 -image $img -anchor $a \
  1143. -tags [Tree::_get_node_tags $path $node [list img i:$node]]
  1144. }
  1145. set box [$path.c bbox n:$node i:$node]
  1146. set id [$path.c create rect 0 [lindex $box 1] \
  1147. [winfo screenwidth $path] [lindex $box 3] \
  1148. -tags [Tree::_get_node_tags $path $node [list box b:$node]] \
  1149. -fill {} -outline {}]
  1150. $path.c lower $id
  1151. _set_help $path $node
  1152. return $y1
  1153. }
  1154. # ----------------------------------------------------------------------------
  1155. # Command Tree::_draw_subnodes
  1156. # ----------------------------------------------------------------------------
  1157. proc Tree::_draw_subnodes { path nodes x0 y0 deltax deltay padx showlines } {
  1158. set y1 $y0
  1159. foreach node $nodes {
  1160. set padx [_get_node_padx $path $node]
  1161. set deltax [_get_node_deltax $path $node]
  1162. set yp $y1
  1163. set y1 [_draw_node $path $node $x0 [expr {$y1+$deltay}] $deltax $deltay $padx $showlines]
  1164. }
  1165. if { $showlines && [llength $nodes] } {
  1166. set id [$path.c create line $x0 $y0 $x0 [expr {$yp+$deltay}] \
  1167. -fill [Widget::getoption $path -linesfill] \
  1168. -stipple [Widget::getoption $path -linestipple] \
  1169. -tags line]
  1170. $path.c lower $id
  1171. }
  1172. return $y1
  1173. }
  1174. # ----------------------------------------------------------------------------
  1175. # Command Tree::_update_nodes
  1176. # ----------------------------------------------------------------------------
  1177. proc Tree::_update_nodes { path } {
  1178. global env
  1179. variable $path
  1180. upvar 0 $path data
  1181. set deltax [Widget::getoption $path -deltax]
  1182. set padx [Widget::getoption $path -padx]
  1183. foreach {node flag} $data(upd,nodes) {
  1184. set idn [$path.c find withtag "n:$node"]
  1185. if { $idn == "" } {
  1186. continue
  1187. }
  1188. set padx [_get_node_padx $path $node]
  1189. set deltax [_get_node_deltax $path $node]
  1190. set c [$path.c coords $idn]
  1191. set x0 [expr {[lindex $c 0]-$padx}]
  1192. set y0 [lindex $c 1]
  1193. if { $flag & 48 } {
  1194. # -window or -image modified
  1195. set win [Widget::getoption $path.$node -window]
  1196. set img [Widget::getoption $path.$node -image]
  1197. set idi [$path.c find withtag i:$node]
  1198. set type [lindex [$path.c gettags $idi] 1]
  1199. if { [string length $win] } {
  1200. if { [string equal $type "win"] } {
  1201. $path.c itemconfigure $idi -window $win
  1202. } else {
  1203. $path.c delete $idi
  1204. $path.c create window $x0 $y0 -window $win -anchor w \
  1205. -tags [Tree::_get_node_tags $path $node \
  1206. [list win i:$node]]
  1207. }
  1208. } elseif { [string length $img] } {
  1209. if { [string equal $type "img"] } {
  1210. $path.c itemconfigure $idi -image $img
  1211. } else {
  1212. $path.c delete $idi
  1213. $path.c create image $x0 $y0 -image $img -anchor w \
  1214. -tags [Tree::_get_node_tags $path $node \
  1215. [list img i:$node]]
  1216. }
  1217. } else {
  1218. $path.c delete $idi
  1219. }
  1220. }
  1221. if { $flag & 8 } {
  1222. # -drawcross modified
  1223. set len [expr {[llength $data($node)] > 1}]
  1224. set dc [Widget::getoption $path.$node -drawcross]
  1225. set exp [Widget::getoption $path.$node -open]
  1226. if {![string equal $dc "never"]
  1227. && ($len || [string equal $dc "allways"])} {
  1228. _draw_cross $path $node $exp $x0 $y0
  1229. } else {
  1230. set idc [$path.c find withtag c:$node]
  1231. $path.c delete $idc
  1232. }
  1233. }
  1234. if { $flag & 7 } {
  1235. # -font, -text or -fill modified
  1236. $path.c itemconfigure $idn \
  1237. -text [Widget::getoption $path.$node -text] \
  1238. -fill [Widget::getoption $path.$node -fill] \
  1239. -font [Widget::getoption $path.$node -font]
  1240. }
  1241. }
  1242. }
  1243. # ----------------------------------------------------------------------------
  1244. # Command Tree::_draw_tree
  1245. # ----------------------------------------------------------------------------
  1246. proc Tree::_draw_tree { path } {
  1247. variable $path
  1248. upvar 0 $path data
  1249. $path.c delete all
  1250. set cursor [$path.c cget -cursor]
  1251. $path.c configure -cursor watch
  1252. _draw_subnodes $path [lrange $data(root) 1 end] 8 \
  1253. [expr {-[Widget::getoption $path -deltay]/2}] \
  1254. [Widget::getoption $path -deltax] \
  1255. [Widget::getoption $path -deltay] \
  1256. [Widget::getoption $path -padx] \
  1257. [Widget::getoption $path -showlines]
  1258. $path.c configure -cursor $cursor
  1259. }
  1260. # ----------------------------------------------------------------------------
  1261. # Command Tree::_redraw_tree
  1262. # ----------------------------------------------------------------------------
  1263. proc Tree::_redraw_tree { path } {
  1264. variable $path
  1265. upvar 0 $path data
  1266. if { [Widget::getoption $path -redraw] } {
  1267. if { $data(upd,level) == 2 } {
  1268. _update_nodes $path
  1269. } elseif { $data(upd,level) == 3 } {
  1270. _draw_tree $path
  1271. }
  1272. _redraw_selection $path
  1273. _update_scrollregion $path
  1274. set data(upd,nodes) {}
  1275. set data(upd,level) 0
  1276. set data(upd,afterid) ""
  1277. }
  1278. }
  1279. # ----------------------------------------------------------------------------
  1280. # Command Tree::_redraw_selection
  1281. # ----------------------------------------------------------------------------
  1282. proc Tree::_redraw_selection { path } {
  1283. variable $path
  1284. upvar 0 $path data
  1285. set selbg [Widget::getoption $path -selectbackground]
  1286. set selfg [Widget::getoption $path -selectforeground]
  1287. set fill [Widget::getoption $path -selectfill]
  1288. if {$fill} {
  1289. set scroll [$path.c cget -scrollregion]
  1290. if {[llength $scroll]} {
  1291. set xmax [expr {[lindex $scroll 2]-1}]
  1292. } else {
  1293. set xmax [winfo width $path]
  1294. }
  1295. }
  1296. foreach id [$path.c find withtag sel] {
  1297. set node [Tree::_get_node_name $path $id 1]
  1298. $path.c itemconfigure "n:$node" -fill [Widget::getoption $path.$node -fill]
  1299. }
  1300. $path.c delete sel
  1301. foreach node $data(selnodes) {
  1302. set bbox [$path.c bbox "n:$node"]
  1303. if { [llength $bbox] } {
  1304. if {$fill} {
  1305. # get the image to (if any), as it may have different height
  1306. set bbox [$path.c bbox "n:$node" "i:$node"]
  1307. set bbox [list 0 [lindex $bbox 1] $xmax [lindex $bbox 3]]
  1308. }
  1309. set id [$path.c create rectangle $bbox -tags [list sel s:$node] \
  1310. -fill $selbg -outline $selbg]
  1311. $path.c itemconfigure "n:$node" -fill $selfg
  1312. $path.c lower $id
  1313. }
  1314. }
  1315. }
  1316. # ----------------------------------------------------------------------------
  1317. # Command Tree::_redraw_idle
  1318. # ----------------------------------------------------------------------------
  1319. proc Tree::_redraw_idle { path level } {
  1320. variabl

Large files files are truncated, but you can click here to view the full file