PageRenderTime 60ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/ASTK_CLIENT/lib/BWidget-1.7.0/listbox.tcl

https://bitbucket.org/mcourtois/codeaster-frontend
TCL | 1614 lines | 1143 code | 217 blank | 254 comment | 257 complexity | 5d56a25236ebc6f89a975f73343716ae MD5 | raw file
Possible License(s): GPL-2.0, AGPL-3.0

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

  1. # ----------------------------------------------------------------------------
  2. # listbox.tcl
  3. # This file is part of Unifix BWidget Toolkit
  4. # $Id: listbox.tcl 606 2004-04-05 07:06:06Z mcourtoi $
  5. # ----------------------------------------------------------------------------
  6. # Index of commands:
  7. # - ListBox::create
  8. # - ListBox::configure
  9. # - ListBox::cget
  10. # - ListBox::insert
  11. # - ListBox::itemconfigure
  12. # - ListBox::itemcget
  13. # - ListBox::bindText
  14. # - ListBox::bindImage
  15. # - ListBox::delete
  16. # - ListBox::move
  17. # - ListBox::reorder
  18. # - ListBox::selection
  19. # - ListBox::exists
  20. # - ListBox::index
  21. # - ListBox::item - deprecated
  22. # - ListBox::items
  23. # - ListBox::see
  24. # - ListBox::edit
  25. # - ListBox::xview
  26. # - ListBox::yview
  27. # - ListBox::_update_edit_size
  28. # - ListBox::_destroy
  29. # - ListBox::_see
  30. # - ListBox::_update_scrollregion
  31. # - ListBox::_draw_item
  32. # - ListBox::_redraw_items
  33. # - ListBox::_redraw_selection
  34. # - ListBox::_redraw_listbox
  35. # - ListBox::_redraw_idle
  36. # - ListBox::_resize
  37. # - ListBox::_init_drag_cmd
  38. # - ListBox::_drop_cmd
  39. # - ListBox::_over_cmd
  40. # - ListBox::_auto_scroll
  41. # - ListBox::_scroll
  42. # ----------------------------------------------------------------------------
  43. namespace eval ListBox {
  44. Widget::define ListBox listbox DragSite DropSite DynamicHelp
  45. namespace eval Item {
  46. Widget::declare ListBox::Item {
  47. {-indent Int 0 0 "%d >= 0"}
  48. {-text String "" 0}
  49. {-font String "" 0}
  50. {-foreground String "" 0}
  51. {-image TkResource "" 0 label}
  52. {-window String "" 0}
  53. {-data String "" 0}
  54. {-fill Synonym -foreground}
  55. {-fg Synonym -foreground}
  56. }
  57. }
  58. DynamicHelp::include ListBox::Item balloon
  59. Widget::tkinclude ListBox canvas .c \
  60. remove {
  61. -insertwidth -insertbackground -insertborderwidth -insertofftime
  62. -insertontime -selectborderwidth -closeenough -confine -scrollregion
  63. -xscrollincrement -yscrollincrement -width -height
  64. } \
  65. initialize {
  66. -relief sunken -borderwidth 2 -takefocus 1
  67. -highlightthickness 1 -width 200
  68. }
  69. DragSite::include ListBox "LISTBOX_ITEM" 1
  70. DropSite::include ListBox {
  71. LISTBOX_ITEM {copy {} move {}}
  72. }
  73. Widget::declare ListBox {
  74. {-deltax Int 10 0 "%d >= 0"}
  75. {-deltay Int 15 0 "%d >= 0"}
  76. {-padx Int 20 0 "%d >= 0"}
  77. {-foreground TkResource "" 0 listbox}
  78. {-background TkResource "" 0 listbox}
  79. {-selectbackground TkResource "" 0 listbox}
  80. {-selectforeground TkResource "" 0 listbox}
  81. {-font TkResource "" 0 listbox}
  82. {-width TkResource "" 0 listbox}
  83. {-height TkResource "" 0 listbox}
  84. {-redraw Boolean 1 0}
  85. {-multicolumn Boolean 0 0}
  86. {-dropovermode Flag "wpi" 0 "wpi"}
  87. {-selectmode Enum none 1 {none single multiple}}
  88. {-fg Synonym -foreground}
  89. {-bg Synonym -background}
  90. {-dropcmd String "ListBox::_drag_and_drop" 0}
  91. {-autofocus Boolean 1 1}
  92. {-selectfill Boolean 0 1}
  93. }
  94. Widget::addmap ListBox "" .c {-deltay -yscrollincrement}
  95. bind ListBox <Destroy> [list ListBox::_destroy %W]
  96. bind ListBox <Configure> [list ListBox::_resize %W]
  97. bind ListBoxFocus <1> [list focus %W]
  98. bind ListBox <Key-Up> [list ListBox::_keyboard_navigation %W -1]
  99. bind ListBox <Key-Down> [list ListBox::_keyboard_navigation %W 1]
  100. variable _edit
  101. }
  102. # ----------------------------------------------------------------------------
  103. # Command ListBox::create
  104. # ----------------------------------------------------------------------------
  105. proc ListBox::create { path args } {
  106. Widget::init ListBox $path $args
  107. variable $path
  108. upvar 0 $path data
  109. frame $path -class ListBox -bd 0 -highlightthickness 0 -relief flat
  110. # For 8.4+ we don't want to inherit the padding
  111. catch {$path configure -padx 0 -pady 0}
  112. # widget informations
  113. set data(nrows) -1
  114. # items informations
  115. set data(items) {}
  116. set data(selitems) {}
  117. # update informations
  118. set data(upd,level) 0
  119. set data(upd,afterid) ""
  120. set data(upd,level) 0
  121. set data(upd,delete) {}
  122. # drag and drop informations
  123. set data(dnd,scroll) ""
  124. set data(dnd,afterid) ""
  125. set data(dnd,item) ""
  126. eval [list canvas $path.c] [Widget::subcget $path .c] \
  127. [list -xscrollincrement 8 -highlightthickness 1]
  128. pack $path.c -expand yes -fill both
  129. DragSite::setdrag $path $path.c ListBox::_init_drag_cmd \
  130. [Widget::cget $path -dragendcmd] 1
  131. DropSite::setdrop $path $path.c ListBox::_over_cmd ListBox::_drop_cmd 1
  132. Widget::create ListBox $path
  133. set w [Widget::cget $path -width]
  134. set h [Widget::cget $path -height]
  135. set dy [Widget::cget $path -deltay]
  136. $path.c configure -width [expr {$w*8}] -height [expr {$h*$dy}]
  137. ## Let any click within the canvas focus on the canvas so that
  138. ## MouseWheel scroll events will be properly handled by the
  139. ## canvas.
  140. if {[Widget::cget $path -autofocus]} {
  141. bindtags $path.c [concat [bindtags $path.c] ListBoxFocus]
  142. BWidget::bindMouseWheel $path.c
  143. }
  144. switch -exact -- [Widget::getoption $path -selectmode] {
  145. single {
  146. $path bindText <Button-1> [list ListBox::_mouse_select $path set]
  147. $path bindImage <Button-1> [list ListBox::_mouse_select $path set]
  148. }
  149. multiple {
  150. set cmd ListBox::_multiple_select
  151. $path bindText <Button-1> [list $cmd $path n %x %y]
  152. $path bindText <Shift-Button-1> [list $cmd $path s %x %y]
  153. $path bindText <Control-Button-1> [list $cmd $path c %x %y]
  154. $path bindImage <Button-1> [list $cmd $path n %x %y]
  155. $path bindImage <Shift-Button-1> [list $cmd $path s %x %y]
  156. $path bindImage <Control-Button-1> [list $cmd $path c %x %y]
  157. }
  158. }
  159. return $path
  160. }
  161. # ----------------------------------------------------------------------------
  162. # Command ListBox::configure
  163. # ----------------------------------------------------------------------------
  164. proc ListBox::configure { path args } {
  165. set res [Widget::configure $path $args]
  166. set ch1 [expr {[Widget::hasChanged $path -deltay dy] |
  167. [Widget::hasChanged $path -padx val] |
  168. [Widget::hasChanged $path -multicolumn val]}]
  169. set ch2 [expr {[Widget::hasChanged $path -selectbackground val] |
  170. [Widget::hasChanged $path -selectforeground val]}]
  171. set redraw 0
  172. if { [Widget::hasChanged $path -height h] } {
  173. $path.c configure -height [expr {$h*$dy}]
  174. set redraw 1
  175. }
  176. if { [Widget::hasChanged $path -width w] } {
  177. $path.c configure -width [expr {$w*8}]
  178. set redraw 1
  179. }
  180. if { [Widget::hasChanged $path -background bg] } {
  181. $path.c itemconfigure box -fill $bg
  182. }
  183. if { !$redraw } {
  184. if { $ch1 } {
  185. _redraw_idle $path 2
  186. } elseif { $ch2 } {
  187. _redraw_idle $path 1
  188. }
  189. }
  190. if { [Widget::hasChanged $path -redraw bool] && $bool } {
  191. variable $path
  192. upvar 0 $path data
  193. set lvl $data(upd,level)
  194. set data(upd,level) 0
  195. _redraw_idle $path $lvl
  196. }
  197. set force [Widget::hasChanged $path -dragendcmd dragend]
  198. DragSite::setdrag $path $path.c ListBox::_init_drag_cmd $dragend $force
  199. DropSite::setdrop $path $path.c ListBox::_over_cmd ListBox::_drop_cmd
  200. return $res
  201. }
  202. # ----------------------------------------------------------------------------
  203. # Command ListBox::cget
  204. # ----------------------------------------------------------------------------
  205. proc ListBox::cget { path option } {
  206. return [Widget::cget $path $option]
  207. }
  208. # ----------------------------------------------------------------------------
  209. # Command ListBox::insert
  210. # ----------------------------------------------------------------------------
  211. proc ListBox::insert { path index item args } {
  212. variable $path
  213. upvar 0 $path data
  214. set item [Widget::nextIndex $path $item]
  215. if { [lsearch -exact $data(items) $item] != -1 } {
  216. return -code error "item \"$item\" already exists"
  217. }
  218. Widget::init ListBox::Item $path.$item $args
  219. set data(items) [linsert $data(items) $index $item]
  220. set data(upd,create,$item) $item
  221. _redraw_idle $path 2
  222. return $item
  223. }
  224. # Bastien Chevreux (bach@mwgdna.com)
  225. # The multipleinsert command performs inserts several items at once into
  226. # the list. It is faster than calling insert multiple times as it uses the
  227. # Widget::copyinit command for initializing all items after the 1st. The
  228. # speedup factor is between 2 and 3 for typical usage, but could be higher
  229. # for inserts with many options.
  230. #
  231. # Syntax: path and index are as in the insert command
  232. # args is a list of even numbered elements where the 1st of each pair
  233. # corresponds to the item of 'insert' and the second to args of 'insert'.
  234. # ----------------------------------------------------------------------------
  235. # Command ListBox::multipleinsert
  236. # ----------------------------------------------------------------------------
  237. proc ListBox::multipleinsert { path index args } {
  238. variable $path
  239. upvar 0 $path data
  240. # If we got only one list as arg, take the first element as args
  241. # This enables callers to use
  242. # $list multipleinsert index $thelist
  243. # instead of
  244. # eval $list multipleinsert index $thelist
  245. if {[llength $args] == 1} {
  246. set args [lindex $args 0]
  247. }
  248. set count 0
  249. foreach {item iargs} $args {
  250. if { [lsearch -exact $data(items) $item] != -1 } {
  251. return -code error "item \"$item\" already exists"
  252. }
  253. if {$count==0} {
  254. Widget::init ListBox::Item $path.$item $iargs
  255. set firstpath $path.$item
  256. } else {
  257. Widget::copyinit ListBox::Item $firstpath $path.$item $iargs
  258. }
  259. set data(items) [linsert $data(items) $index $item]
  260. set data(upd,create,$item) $item
  261. incr count
  262. }
  263. _redraw_idle $path 2
  264. return $item
  265. }
  266. # ----------------------------------------------------------------------------
  267. # Command ListBox::itemconfigure
  268. # ----------------------------------------------------------------------------
  269. proc ListBox::itemconfigure { path item args } {
  270. variable $path
  271. upvar 0 $path data
  272. if { [lsearch -exact $data(items) $item] == -1 } {
  273. return -code error "item \"$item\" does not exist"
  274. }
  275. set oldind [Widget::getoption $path.$item -indent]
  276. set res [Widget::configure $path.$item $args]
  277. set chind [Widget::hasChanged $path.$item -indent indent]
  278. set chw [Widget::hasChanged $path.$item -window win]
  279. set chi [Widget::hasChanged $path.$item -image img]
  280. set cht [Widget::hasChanged $path.$item -text txt]
  281. set chf [Widget::hasChanged $path.$item -font fnt]
  282. set chfg [Widget::hasChanged $path.$item -foreground fg]
  283. set idn [$path.c find withtag n:$item]
  284. _set_help $path $item
  285. if { $idn == "" } {
  286. # item is not drawn yet
  287. _redraw_idle $path 2
  288. return $res
  289. }
  290. set oldb [$path.c bbox $idn]
  291. set coords [$path.c coords $idn]
  292. set padx [Widget::getoption $path -padx]
  293. set x0 [expr {[lindex $coords 0]-$padx-$oldind+$indent}]
  294. set y0 [lindex $coords 1]
  295. if { $chw || $chi } {
  296. # -window or -image modified
  297. set idi [$path.c find withtag i:$item]
  298. set type [lindex [$path.c gettags $idi] 0]
  299. if { [string length $win] } {
  300. if { [string equal $type "win"] } {
  301. $path.c itemconfigure $idi -window $win
  302. } else {
  303. $path.c delete $idi
  304. $path.c create window $x0 $y0 -window $win -anchor w \
  305. -tags [list win i:$item]
  306. }
  307. } elseif { [string length $img] } {
  308. if { [string equal $type "img"] } {
  309. $path.c itemconfigure $idi -image $img
  310. } else {
  311. $path.c delete $idi
  312. $path.c create image $x0 $y0 -image $img -anchor w \
  313. -tags [list img i:$item]
  314. }
  315. } else {
  316. $path.c delete $idi
  317. }
  318. }
  319. if { $cht || $chf || $chfg } {
  320. # -text or -font modified, or -foreground modified
  321. set fnt [_getoption $path $item -font]
  322. set fg [_getoption $path $item -foreground]
  323. $path.c itemconfigure $idn -text $txt -font $fnt -fill $fg
  324. _redraw_idle $path 1
  325. }
  326. if { $chind } {
  327. # -indent modified
  328. $path.c coords $idn [expr {$x0+$padx}] $y0
  329. $path.c coords i:$item $x0 $y0
  330. _redraw_idle $path 1
  331. }
  332. if { [Widget::getoption $path -multicolumn] && ($cht || $chf || $chind) } {
  333. set bbox [$path.c bbox $idn]
  334. if { [lindex $bbox 2] > [lindex $oldb 2] } {
  335. _redraw_idle $path 2
  336. }
  337. }
  338. return $res
  339. }
  340. # ----------------------------------------------------------------------------
  341. # Command ListBox::itemcget
  342. # ----------------------------------------------------------------------------
  343. proc ListBox::itemcget { path item option } {
  344. return [Widget::cget $path.$item $option]
  345. }
  346. # ----------------------------------------------------------------------------
  347. # Command ListBox::bindText
  348. # ----------------------------------------------------------------------------
  349. proc ListBox::bindText { path event script } {
  350. if { $script != "" } {
  351. set map [list %W $path]
  352. set script [string map $map $script]
  353. $path.c bind "click" $event "$script \[ListBox::_get_current $path]"
  354. } else {
  355. $path.c bind "click" $event {}
  356. }
  357. }
  358. # ----------------------------------------------------------------------------
  359. # Command ListBox::bindImage
  360. # ----------------------------------------------------------------------------
  361. proc ListBox::bindImage { path event script } {
  362. if { $script != "" } {
  363. set map [list %W $path]
  364. set script [string map $map $script]
  365. $path.c bind "img" $event "$script \[ListBox::_get_current $path]"
  366. } else {
  367. $path.c bind "img" $event {}
  368. }
  369. }
  370. # ----------------------------------------------------------------------------
  371. # Command ListBox::delete
  372. # ----------------------------------------------------------------------------
  373. proc ListBox::delete { path args } {
  374. variable $path
  375. upvar 0 $path data
  376. foreach litems $args {
  377. foreach item $litems {
  378. set idx [lsearch -exact $data(items) $item]
  379. if { $idx != -1 } {
  380. set data(items) [lreplace $data(items) $idx $idx]
  381. Widget::destroy $path.$item
  382. if { [info exists data(upd,create,$item)] } {
  383. unset data(upd,create,$item)
  384. } else {
  385. lappend data(upd,delete) $item
  386. }
  387. }
  388. }
  389. }
  390. set sel $data(selitems)
  391. set data(selitems) {}
  392. eval [list selection $path set] $sel
  393. _redraw_idle $path 2
  394. }
  395. # ----------------------------------------------------------------------------
  396. # Command ListBox::move
  397. # ----------------------------------------------------------------------------
  398. proc ListBox::move { path item index } {
  399. variable $path
  400. upvar 0 $path data
  401. if { [set idx [lsearch -exact $data(items) $item]] == -1 } {
  402. return -code error "item \"$item\" does not exist"
  403. }
  404. set data(items) [linsert [lreplace $data(items) $idx $idx] $index $item]
  405. _redraw_idle $path 2
  406. }
  407. # ----------------------------------------------------------------------------
  408. # Command ListBox::reorder
  409. # ----------------------------------------------------------------------------
  410. proc ListBox::reorder { path neworder } {
  411. variable $path
  412. upvar 0 $path data
  413. set data(items) [BWidget::lreorder $data(items) $neworder]
  414. _redraw_idle $path 2
  415. }
  416. # ----------------------------------------------------------------------------
  417. # Command ListBox::selection
  418. # ----------------------------------------------------------------------------
  419. proc ListBox::selection { path cmd args } {
  420. variable $path
  421. upvar 0 $path data
  422. switch -- $cmd {
  423. set {
  424. set data(selitems) {}
  425. foreach item $args {
  426. if { [lsearch -exact $data(selitems) $item] == -1 } {
  427. if { [lsearch -exact $data(items) $item] != -1 } {
  428. lappend data(selitems) $item
  429. }
  430. }
  431. }
  432. }
  433. add {
  434. foreach item $args {
  435. if { [lsearch -exact $data(selitems) $item] == -1 } {
  436. if { [lsearch -exact $data(items) $item] != -1 } {
  437. lappend data(selitems) $item
  438. }
  439. }
  440. }
  441. }
  442. remove {
  443. foreach item $args {
  444. if { [set idx [lsearch -exact $data(selitems) $item]] != -1 } {
  445. set data(selitems) [lreplace $data(selitems) $idx $idx]
  446. }
  447. }
  448. }
  449. clear {
  450. set data(selitems) {}
  451. }
  452. get {
  453. return $data(selitems)
  454. }
  455. includes {
  456. return [expr {[lsearch -exact $data(selitems) $args] != -1}]
  457. }
  458. default {
  459. return
  460. }
  461. }
  462. _redraw_idle $path 1
  463. }
  464. # ----------------------------------------------------------------------------
  465. # Command ListBox::exists
  466. # ----------------------------------------------------------------------------
  467. proc ListBox::exists { path item } {
  468. variable $path
  469. upvar 0 $path data
  470. return [expr {[lsearch -exact $data(items) $item] != -1}]
  471. }
  472. # ----------------------------------------------------------------------------
  473. # Command ListBox::index
  474. # ----------------------------------------------------------------------------
  475. proc ListBox::index { path item } {
  476. variable $path
  477. upvar 0 $path data
  478. if {[string equal $item "active"]} { return [$path selection get] }
  479. return [lsearch -exact $data(items) $item]
  480. }
  481. # ----------------------------------------------------------------------------
  482. # ListBox::find
  483. # Returns the item given a position.
  484. # findInfo @x,y ?confine?
  485. # lineNumber
  486. # ----------------------------------------------------------------------------
  487. proc ListBox::find {path findInfo {confine ""}} {
  488. variable $path
  489. upvar 0 $path widgetData
  490. if {[regexp -- {^@([0-9]+),([0-9]+)$} $findInfo match x y]} {
  491. set x [$path.c canvasx $x]
  492. set y [$path.c canvasy $y]
  493. } elseif {[regexp -- {^[0-9]+$} $findInfo lineNumber]} {
  494. set dy [Widget::getoption $path -deltay]
  495. set y [expr {$dy*($lineNumber+0.5)}]
  496. set confine ""
  497. } else {
  498. return -code error "invalid find spec \"$findInfo\""
  499. }
  500. set found 0
  501. set xi 0
  502. foreach xs $widgetData(xlist) {
  503. if {$x <= $xs} {
  504. foreach id [$path.c find overlapping $xi $y $xs $y] {
  505. set ltags [$path.c gettags $id]
  506. set item [lindex $ltags 0]
  507. if { [string equal $item "item"] ||
  508. [string equal $item "img"] ||
  509. [string equal $item "win"] } {
  510. # item is the label or image/window of the node
  511. set item [string range [lindex $ltags 1] 2 end]
  512. set found 1
  513. break
  514. }
  515. }
  516. break
  517. }
  518. set xi $xs
  519. }
  520. if {$found} {
  521. if {[string equal $confine "confine"]} {
  522. # test if x stand inside node bbox
  523. set xi [expr {[lindex [$path.c coords n:$item] 0]-[Widget::getoption $path -padx]}]
  524. set xs [lindex [$path.c bbox n:$item] 2]
  525. if {$x >= $xi && $x <= $xs} {
  526. return $item
  527. }
  528. } else {
  529. return $item
  530. }
  531. }
  532. return ""
  533. }
  534. # ----------------------------------------------------------------------------
  535. # Command ListBox::item - deprecated
  536. # ----------------------------------------------------------------------------
  537. proc ListBox::item { path first {last ""} } {
  538. variable $path
  539. upvar 0 $path data
  540. if { ![string length $last] } {
  541. return [lindex $data(items) $first]
  542. } else {
  543. return [lrange $data(items) $first $last]
  544. }
  545. }
  546. # ----------------------------------------------------------------------------
  547. # Command ListBox::items
  548. # ----------------------------------------------------------------------------
  549. proc ListBox::items { path {first ""} {last ""}} {
  550. variable $path
  551. upvar 0 $path data
  552. if { ![string length $first] } {
  553. return $data(items)
  554. }
  555. if { ![string length $last] } {
  556. return [lindex $data(items) $first]
  557. } else {
  558. return [lrange $data(items) $first $last]
  559. }
  560. }
  561. # ----------------------------------------------------------------------------
  562. # Command ListBox::see
  563. # ----------------------------------------------------------------------------
  564. proc ListBox::see { path item } {
  565. variable $path
  566. upvar 0 $path data
  567. if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
  568. after cancel $data(upd,afterid)
  569. _redraw_listbox $path
  570. }
  571. set idn [$path.c find withtag n:$item]
  572. if { $idn != "" } {
  573. ListBox::_see $path $idn right
  574. ListBox::_see $path $idn left
  575. }
  576. }
  577. # ----------------------------------------------------------------------------
  578. # Command ListBox::edit
  579. # ----------------------------------------------------------------------------
  580. proc ListBox::edit { path item text {verifycmd ""} {clickres 0} {select 1}} {
  581. variable _edit
  582. variable $path
  583. upvar 0 $path data
  584. if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
  585. after cancel $data(upd,afterid)
  586. _redraw_listbox $path
  587. }
  588. set idn [$path.c find withtag n:$item]
  589. if { $idn != "" } {
  590. ListBox::_see $path $idn right
  591. ListBox::_see $path $idn left
  592. set oldfg [$path.c itemcget $idn -fill]
  593. set sbg [Widget::getoption $path -selectbackground]
  594. set coords [$path.c coords $idn]
  595. set x [lindex $coords 0]
  596. set y [lindex $coords 1]
  597. set bd [expr {[$path.c cget -borderwidth]+[$path.c cget -highlightthickness]}]
  598. set w [expr {[winfo width $path] - 2*$bd}]
  599. set wmax [expr {[$path.c canvasx $w]-$x}]
  600. $path.c itemconfigure $idn -fill [Widget::getoption $path -background]
  601. $path.c itemconfigure s:$item -fill {} -outline {}
  602. set _edit(text) $text
  603. set _edit(wait) 0
  604. set frame [frame $path.edit \
  605. -relief flat -borderwidth 0 -highlightthickness 0 \
  606. -background [Widget::getoption $path -background]]
  607. set ent [entry $frame.edit \
  608. -width 0 \
  609. -relief solid \
  610. -borderwidth 1 \
  611. -highlightthickness 0 \
  612. -foreground [_getoption $path $item -foreground] \
  613. -background [Widget::getoption $path -background] \
  614. -selectforeground [Widget::getoption $path -selectforeground] \
  615. -selectbackground $sbg \
  616. -font [_getoption $path $item -font] \
  617. -textvariable ListBox::_edit(text)]
  618. pack $ent -ipadx 8 -anchor w
  619. set idw [$path.c create window $x $y -window $frame -anchor w]
  620. trace variable ListBox::_edit(text) w [list ListBox::_update_edit_size $path $ent $idw $wmax]
  621. tkwait visibility $ent
  622. grab $frame
  623. BWidget::focus set $ent
  624. _update_edit_size $path $ent $idw $wmax
  625. update
  626. if { $select } {
  627. $ent selection range 0 end
  628. $ent icursor end
  629. $ent xview end
  630. }
  631. bindtags $ent [list $ent Entry]
  632. bind $ent <Escape> {set ListBox::_edit(wait) 0}
  633. bind $ent <Return> {set ListBox::_edit(wait) 1}
  634. if { $clickres == 0 || $clickres == 1 } {
  635. bind $frame <Button> [list set ListBox::_edit(wait) $clickres]
  636. }
  637. set ok 0
  638. while { !$ok } {
  639. tkwait variable ListBox::_edit(wait)
  640. if { !$_edit(wait) || $verifycmd == "" ||
  641. [uplevel \#0 $verifycmd [list $_edit(text)]] } {
  642. set ok 1
  643. }
  644. }
  645. trace vdelete ListBox::_edit(text) w [list ListBox::_update_edit_size $path $ent $idw $wmax]
  646. grab release $frame
  647. BWidget::focus release $ent
  648. destroy $frame
  649. $path.c delete $idw
  650. $path.c itemconfigure $idn -fill $oldfg
  651. $path.c itemconfigure s:$item -fill $sbg -outline $sbg
  652. if { $_edit(wait) } {
  653. return $_edit(text)
  654. }
  655. }
  656. return ""
  657. }
  658. # ----------------------------------------------------------------------------
  659. # Command ListBox::xview
  660. # ----------------------------------------------------------------------------
  661. proc ListBox::xview { path args } {
  662. return [eval [list $path.c xview] $args]
  663. }
  664. # ----------------------------------------------------------------------------
  665. # Command ListBox::yview
  666. # ----------------------------------------------------------------------------
  667. proc ListBox::yview { path args } {
  668. return [eval [list $path.c yview] $args]
  669. }
  670. proc ListBox::getcanvas { path } {
  671. return $path.c
  672. }
  673. proc ListBox::curselection { path } {
  674. return [$path selection get]
  675. }
  676. # ----------------------------------------------------------------------------
  677. # Command ListBox::_update_edit_size
  678. # ----------------------------------------------------------------------------
  679. proc ListBox::_update_edit_size { path entry idw wmax args } {
  680. set entw [winfo reqwidth $entry]
  681. if { $entw >= $wmax } {
  682. $path.c itemconfigure $idw -width $wmax
  683. } else {
  684. $path.c itemconfigure $idw -width 0
  685. }
  686. }
  687. # ----------------------------------------------------------------------------
  688. # Command ListBox::_getoption
  689. # Returns the value of option for node. If empty, returned value is those
  690. # of the ListBox.
  691. # ----------------------------------------------------------------------------
  692. proc ListBox::_getoption { path item option } {
  693. set value [Widget::getoption $path.$item $option]
  694. if {![string length $value]} {
  695. set value [Widget::getoption $path $option]
  696. }
  697. return $value
  698. }
  699. # ----------------------------------------------------------------------------
  700. # Command ListBox::_destroy
  701. # ----------------------------------------------------------------------------
  702. proc ListBox::_destroy { path } {
  703. variable $path
  704. upvar 0 $path data
  705. if { $data(upd,afterid) != "" } {
  706. after cancel $data(upd,afterid)
  707. }
  708. if { $data(dnd,afterid) != "" } {
  709. after cancel $data(dnd,afterid)
  710. }
  711. foreach item $data(items) {
  712. Widget::destroy $path.$item
  713. }
  714. Widget::destroy $path
  715. unset data
  716. }
  717. # ----------------------------------------------------------------------------
  718. # Command ListBox::_see
  719. # ----------------------------------------------------------------------------
  720. proc ListBox::_see { path idn side } {
  721. set bbox [$path.c bbox $idn]
  722. set scrl [$path.c cget -scrollregion]
  723. set ymax [lindex $scrl 3]
  724. set dy [$path.c cget -yscrollincrement]
  725. set yv [$path.c yview]
  726. set yv0 [expr {round([lindex $yv 0]*$ymax/$dy)}]
  727. set yv1 [expr {round([lindex $yv 1]*$ymax/$dy)}]
  728. set y [expr {int([lindex [$path.c coords $idn] 1]/$dy)}]
  729. if { $y < $yv0 } {
  730. $path.c yview scroll [expr {$y-$yv0}] units
  731. } elseif { $y >= $yv1 } {
  732. $path.c yview scroll [expr {$y-$yv1+1}] units
  733. }
  734. set xmax [lindex $scrl 2]
  735. set dx [$path.c cget -xscrollincrement]
  736. set xv [$path.c xview]
  737. if { [string equal $side "right"] } {
  738. set xv1 [expr {round([lindex $xv 1]*$xmax/$dx)}]
  739. set x1 [expr {int([lindex $bbox 2]/$dx)}]
  740. if { $x1 >= $xv1 } {
  741. $path.c xview scroll [expr {$x1-$xv1+1}] units
  742. }
  743. } else {
  744. set xv0 [expr {round([lindex $xv 0]*$xmax/$dx)}]
  745. set x0 [expr {int([lindex $bbox 0]/$dx)}]
  746. if { $x0 < $xv0 } {
  747. $path.c xview scroll [expr {$x0-$xv0}] units
  748. }
  749. }
  750. }
  751. # ----------------------------------------------------------------------------
  752. # Command ListBox::_update_scrollregion
  753. # ----------------------------------------------------------------------------
  754. proc ListBox::_update_scrollregion { path } {
  755. set bd [$path.c cget -borderwidth]
  756. set ht [$path.c cget -highlightthickness]
  757. set bd [expr {2*($bd + $ht)}]
  758. set w [expr {[winfo width $path] - $bd}]
  759. set h [expr {[winfo height $path] - $bd}]
  760. set xinc [$path.c cget -xscrollincrement]
  761. set yinc [$path.c cget -yscrollincrement]
  762. set bbox [$path.c bbox item win img]
  763. if { [llength $bbox] } {
  764. set xs [lindex $bbox 2]
  765. set ys [lindex $bbox 3]
  766. if { $w < $xs } {
  767. set w [expr {int($xs)}]
  768. if { [set r [expr {$w % $xinc}]] } {
  769. set w [expr {$w+$xinc-$r}]
  770. }
  771. }
  772. if { $h < $ys } {
  773. set h [expr {int($ys)}]
  774. if { [set r [expr {$h % $yinc}]] } {
  775. set h [expr {$h+$yinc-$r}]
  776. }
  777. }
  778. }
  779. $path.c configure -scrollregion [list 0 0 $w $h]
  780. }
  781. proc ListBox::_update_select_fill { path } {
  782. variable $path
  783. upvar 0 $path data
  784. set width [winfo width $path]
  785. foreach item $data(items) {
  786. set bbox [$path.c bbox n:$item]
  787. set bbox [list 0 [lindex $bbox 1] $width [lindex $bbox 3]]
  788. $path.c coords b:$item $bbox
  789. }
  790. _redraw_selection $path
  791. }
  792. # ----------------------------------------------------------------------------
  793. # Command ListBox::_draw_item
  794. # ----------------------------------------------------------------------------
  795. proc ListBox::_draw_item { path item x0 x1 y } {
  796. set indent [Widget::getoption $path.$item -indent]
  797. set selfill [Widget::cget $path -selectfill]
  798. set multi [Widget::cget $path -multicolumn]
  799. set i [$path.c create text [expr {$x1+$indent}] $y \
  800. -text [Widget::getoption $path.$item -text] \
  801. -fill [_getoption $path $item -foreground] \
  802. -font [_getoption $path $item -font] \
  803. -anchor w \
  804. -tags [list item n:$item click]]
  805. if { $selfill && !$multi } {
  806. set bg [Widget::cget $path -background]
  807. set width [winfo width $path.c]
  808. set bbox [$path.c bbox n:$item]
  809. set bbox [list 0 [lindex $bbox 1] $width [lindex $bbox 3]]
  810. set tags [list box b:$item click]
  811. $path.c create rect $bbox -fill $bg -width 0 -tags $tags
  812. $path.c raise $i
  813. }
  814. if { [set win [Widget::getoption $path.$item -window]] != "" } {
  815. $path.c create window [expr {$x0+$indent}] $y \
  816. -window $win -anchor w -tags [list win i:$item]
  817. } elseif { [set img [Widget::getoption $path.$item -image]] != "" } {
  818. $path.c create image [expr {$x0+$indent}] $y \
  819. -image $img -anchor w -tags [list img i:$item]
  820. }
  821. _set_help $path $item
  822. }
  823. # ----------------------------------------------------------------------------
  824. # Command ListBox::_redraw_items
  825. # ----------------------------------------------------------------------------
  826. proc ListBox::_redraw_items { path } {
  827. variable $path
  828. upvar 0 $path data
  829. set cursor [$path.c cget -cursor]
  830. $path.c configure -cursor watch
  831. set dx [Widget::getoption $path -deltax]
  832. set dy [Widget::getoption $path -deltay]
  833. set padx [Widget::getoption $path -padx]
  834. set y0 [expr {$dy/2}]
  835. set x0 4
  836. set x1 [expr {$x0+$padx}]
  837. set nitem 0
  838. set drawn {}
  839. set data(xlist) {}
  840. if { [Widget::cget $path -multicolumn] } {
  841. set nrows $data(nrows)
  842. } else {
  843. set nrows [llength $data(items)]
  844. }
  845. foreach item $data(upd,delete) {
  846. $path.c delete i:$item n:$item s:$item b:$item
  847. }
  848. foreach item $data(items) {
  849. if { [info exists data(upd,create,$item)] } {
  850. _draw_item $path $item $x0 $x1 $y0
  851. unset data(upd,create,$item)
  852. } else {
  853. set indent [Widget::getoption $path.$item -indent]
  854. $path.c coords n:$item [expr {$x1+$indent}] $y0
  855. $path.c coords i:$item [expr {$x0+$indent}] $y0
  856. }
  857. incr y0 $dy
  858. incr nitem
  859. lappend drawn n:$item
  860. if { $nitem == $nrows } {
  861. set y0 [expr {$dy/2}]
  862. set bbox [eval [list $path.c bbox] $drawn]
  863. set drawn {}
  864. set x0 [expr {[lindex $bbox 2]+$dx}]
  865. set x1 [expr {$x0+$padx}]
  866. set nitem 0
  867. lappend data(xlist) [lindex $bbox 2]
  868. }
  869. }
  870. if { $nitem && $nitem < $nrows } {
  871. set bbox [eval [list $path.c bbox] $drawn]
  872. lappend data(xlist) [lindex $bbox 2]
  873. }
  874. set data(upd,delete) {}
  875. $path.c configure -cursor $cursor
  876. }
  877. # ----------------------------------------------------------------------------
  878. # Command ListBox::_redraw_selection
  879. # ----------------------------------------------------------------------------
  880. proc ListBox::_redraw_selection { path } {
  881. variable $path
  882. upvar 0 $path data
  883. set selbg [Widget::getoption $path -selectbackground]
  884. set selfg [Widget::getoption $path -selectforeground]
  885. set selfill [Widget::getoption $path -selectfill]
  886. set multi [Widget::getoption $path -multicolumn]
  887. foreach id [$path.c find withtag sel] {
  888. set item [string range [lindex [$path.c gettags $id] 1] 2 end]
  889. $path.c itemconfigure "n:$item" \
  890. -fill [_getoption $path $item -foreground]
  891. }
  892. $path.c delete sel
  893. foreach item $data(selitems) {
  894. set bbox [$path.c bbox "n:$item"]
  895. if { $selfill && !$multi } {
  896. set bbox2 [$path.c bbox "b:$item"]
  897. set w1 [lindex $bbox 2]
  898. set w2 [lindex $bbox2 2]
  899. if {$w1 < $w2} { set bbox $bbox2 }
  900. }
  901. if { [llength $bbox] } {
  902. set tags [list sel s:$item click]
  903. set id [$path.c create rectangle $bbox \
  904. -fill $selbg -outline $selbg -tags $tags]
  905. $path.c itemconfigure "n:$item" -fill $selfg
  906. $path.c lower $id
  907. $path.c lower b:$item
  908. }
  909. }
  910. }
  911. # ----------------------------------------------------------------------------
  912. # Command ListBox::_redraw_listbox
  913. # ----------------------------------------------------------------------------
  914. proc ListBox::_redraw_listbox { path } {
  915. variable $path
  916. upvar 0 $path data
  917. if { [Widget::getoption $path -redraw] } {
  918. if { $data(upd,level) == 2 } {
  919. _redraw_items $path
  920. }
  921. _redraw_selection $path
  922. _update_scrollregion $path
  923. set data(upd,level) 0
  924. set data(upd,afterid) ""
  925. }
  926. }
  927. # ----------------------------------------------------------------------------
  928. # Command ListBox::_redraw_idle
  929. # ----------------------------------------------------------------------------
  930. proc ListBox::_redraw_idle { path level } {
  931. variable $path
  932. upvar 0 $path data
  933. if { $data(nrows) != -1 } {
  934. # widget is realized
  935. if { [Widget::getoption $path -redraw] && $data(upd,afterid) == "" } {
  936. set data(upd,afterid) [after idle ListBox::_redraw_listbox $path]
  937. }
  938. }
  939. if { $level > $data(upd,level) } {
  940. set data(upd,level) $level
  941. }
  942. return ""
  943. }
  944. # ----------------------------------------------------------------------------
  945. # Command ListBox::_resize
  946. # ----------------------------------------------------------------------------
  947. proc ListBox::_resize { path } {
  948. variable $path
  949. upvar 0 $path data
  950. if { [Widget::getoption $path -multicolumn] } {
  951. set bd [expr {[$path.c cget -borderwidth]+[$path.c cget -highlightthickness]}]
  952. set h [expr {[winfo height $path] - 2*$bd}]
  953. set nrows [expr {$h/[$path.c cget -yscrollincrement]}]
  954. if { $nrows == 0 } {
  955. set nrows 1
  956. }
  957. if { $nrows != $data(nrows) } {
  958. set data(nrows) $nrows
  959. _redraw_idle $path 2
  960. } else {
  961. _update_scrollregion $path
  962. }
  963. } elseif { $data(nrows) == -1 } {
  964. # first Configure event
  965. set data(nrows) 0
  966. ListBox::_redraw_listbox $path
  967. if {[Widget::cget $path -selectfill]} {
  968. _update_select_fill $path
  969. }
  970. } else {
  971. if {[Widget::cget $path -selectfill]} {
  972. _update_select_fill $path
  973. }
  974. _update_scrollregion $path
  975. }
  976. }
  977. # ----------------------------------------------------------------------------
  978. # Command ListBox::_init_drag_cmd
  979. # ----------------------------------------------------------------------------
  980. proc ListBox::_init_drag_cmd { path X Y top } {
  981. set path [winfo parent $path]
  982. set ltags [$path.c gettags current]
  983. set item [lindex $ltags 0]
  984. if { [string equal $item "item"] ||
  985. [string equal $item "img"] ||
  986. [string equal $item "win"] } {
  987. set item [string range [lindex $ltags 1] 2 end]
  988. if { [set cmd [Widget::getoption $path -draginitcmd]] != "" } {
  989. return [uplevel \#0 $cmd [list $path $item $top]]
  990. }
  991. if { [set type [Widget::getoption $path -dragtype]] == "" } {
  992. set type "LISTBOX_ITEM"
  993. }
  994. if { [set img [Widget::getoption $path.$item -image]] != "" } {
  995. pack [label $top.l -image $img -padx 0 -pady 0]
  996. }
  997. return [list $type {copy move link} $item]
  998. }
  999. return {}
  1000. }
  1001. # ----------------------------------------------------------------------------
  1002. # Command ListBox::_drop_cmd
  1003. # ----------------------------------------------------------------------------
  1004. proc ListBox::_drop_cmd { path source X Y op type dnddata } {
  1005. set path [winfo parent $path]
  1006. variable $path
  1007. upvar 0 $path data
  1008. if { [string length $data(dnd,afterid)] } {
  1009. after cancel $data(dnd,afterid)
  1010. set data(dnd,afterid) ""
  1011. }
  1012. $path.c delete drop
  1013. set data(dnd,scroll) ""
  1014. if { [llength $data(dnd,item)] || ![llength $data(items)] } {
  1015. if { [set cmd [Widget::getoption $path -dropcmd]] != "" } {
  1016. return [uplevel \#0 $cmd [list $path $source $data(dnd,item) $op $type $dnddata]]
  1017. }
  1018. }
  1019. return 0
  1020. }
  1021. # ----------------------------------------------------------------------------
  1022. # Command ListBox::_over_cmd
  1023. # ----------------------------------------------------------------------------
  1024. proc ListBox::_over_cmd { path source event X Y op type dnddata } {
  1025. set path [winfo parent $path]
  1026. variable $path
  1027. upvar 0 $path data
  1028. if { [string equal $event "leave"] } {
  1029. # we leave the window listbox
  1030. $path.c delete drop
  1031. if { [string length $data(dnd,afterid)] } {
  1032. after cancel $data(dnd,afterid)
  1033. set data(dnd,afterid) ""
  1034. }
  1035. set data(dnd,scroll) ""
  1036. return 0
  1037. }
  1038. if { [string equal $event "enter"] } {
  1039. # we enter the window listbox - dnd data initialization
  1040. set mode [Widget::getoption $path -dropovermode]
  1041. set data(dnd,mode) 0
  1042. foreach c {w p i} {
  1043. set data(dnd,mode) [expr {($data(dnd,mode) << 1) | ([string first $c $mode] != -1)}]
  1044. }
  1045. }
  1046. set x [expr {$X-[winfo rootx $path]}]
  1047. set y [expr {$Y-[winfo rooty $path]}]
  1048. $path.c delete drop
  1049. set data(dnd,item) ""
  1050. # test for auto-scroll unless mode is widget only
  1051. if { $data(dnd,mode) != 4 && [_auto_scroll $path $x $y] != "" } {
  1052. return 2
  1053. }
  1054. if { $data(dnd,mode) & 4 } {
  1055. # dropovermode includes widget
  1056. set target [list widget]
  1057. set vmode 4
  1058. } else {
  1059. set target [list ""]
  1060. set vmode 0
  1061. }
  1062. if { ($data(dnd,mode) & 2) && ![llength $data(items)] } {
  1063. # dropovermode includes position and listbox is empty
  1064. lappend target "" 0
  1065. set vmode [expr {$vmode | 2}]
  1066. }
  1067. if { ($data(dnd,mode) & 3) && [llength $data(items)]} {
  1068. # dropovermode includes item or position
  1069. # we extract the box (xi,yi,xs,ys) where we can find item around x,y
  1070. set len [llength $data(items)]
  1071. set xc [$path.c canvasx $x]
  1072. set yc [$path.c canvasy $y]
  1073. set dy [$path.c cget -yscrollincrement]
  1074. set line [expr {int($yc/$dy)}]
  1075. set yi [expr {$line*$dy}]
  1076. set ys [expr {$yi+$dy}]
  1077. set xi 0
  1078. set pos $line
  1079. if { [Widget::getoption $path -multicolumn] } {
  1080. set nrows $data(nrows)
  1081. } else {
  1082. set nrows $len
  1083. }
  1084. if { $line < $nrows } {
  1085. foreach xs $data(xlist) {
  1086. if { $xc <= $xs } {
  1087. break
  1088. }
  1089. set xi $xs
  1090. incr pos $nrows
  1091. }
  1092. if { $pos < $len } {
  1093. set item [lindex $data(items) $pos]
  1094. set xi [expr {[lindex [$path.c coords n:$item] 0]-[Widget::getoption $path -padx]-1}]
  1095. if { $data(dnd,mode) & 1 } {
  1096. # dropovermode includes item
  1097. lappend target $item
  1098. set vmode [expr {$vmode | 1}]
  1099. } else {
  1100. lappend target ""
  1101. }
  1102. if { $data(dnd,mode) & 2 } {
  1103. # dropovermode includes position
  1104. if { $yc >= $yi+$dy/2 } {
  1105. # position is after $item
  1106. incr pos
  1107. set yl $ys
  1108. } else {
  1109. # position is before $item
  1110. set yl $yi
  1111. }
  1112. lappend target $pos
  1113. set vmode [expr {$vmode | 2}]
  1114. } else {
  1115. lappend target ""
  1116. }
  1117. } else {
  1118. lappend target "" ""
  1119. }
  1120. } else {
  1121. lappend target "" ""
  1122. }
  1123. if { ($vmode & 3) == 3 } {
  1124. # result have both item and position
  1125. # we compute what is the preferred method
  1126. if { $yc-$yi <= 3 || $ys-$yc <= 3 } {
  1127. lappend target "position"
  1128. } else {
  1129. lappend target "item"
  1130. }
  1131. }
  1132. }
  1133. if { $vmode && [set cmd [Widget::getoption $path -dropovercmd]] != "" } {
  1134. # user-defined dropover command
  1135. set res [uplevel \#0 $cmd [list $source $target $op $type $dnddata]]
  1136. set code [lindex $res 0]
  1137. set vmode 0
  1138. if {$code & 1} {
  1139. # update vmode
  1140. switch -exact -- [lindex $res 1] {
  1141. item {set vmode 1}
  1142. position {set vmode 2}
  1143. widget {set vmode 4}
  1144. }
  1145. }
  1146. } else {
  1147. if { ($vmode & 3) == 3 } {
  1148. # result have both item and position
  1149. # we choose the preferred method
  1150. if { [string equal [lindex $target 3] "position"] } {
  1151. set vmode [expr {$vmode & ~1}]
  1152. } else {
  1153. set vmode [expr {$vmode & ~2}]
  1154. }
  1155. }
  1156. if { $data(dnd,mode) == 4 || $data(dnd,mode) == 0 } {
  1157. # dropovermode is widget or empty - recall is not necessary
  1158. set code 1
  1159. } else {
  1160. set code 3
  1161. }
  1162. }
  1163. # draw dnd visual following vmode
  1164. if {[llength $data(items)]} {
  1165. if { $vmode & 1 } {
  1166. set data(dnd,item) [list "item" [lindex $target 1]]
  1167. $path.c create rectangle $xi $yi $xs $ys -tags drop
  1168. } elseif { $vmode & 2 } {
  1169. set data(dnd,item) [concat "position" [lindex $target 2]]
  1170. $path.c create line $xi $yl $xs $yl -tags drop
  1171. } elseif { $vmode & 4 } {
  1172. set data(dnd,item) [list "widget"]
  1173. } else {
  1174. set code [expr {$code & 2}]
  1175. }
  1176. }
  1177. if { $code & 1 } {
  1178. DropSite::setcursor based_arrow_down
  1179. } else {
  1180. DropSite::setcursor dot
  1181. }
  1182. return $code
  1183. }
  1184. # ----------------------------------------------------------------------------
  1185. # Command ListBox::_auto_scroll
  1186. # ----------------------------------------------------------------------------
  1187. proc ListBox::_auto_scroll { path x y } {
  1188. variable $path
  1189. upvar 0 $path data
  1190. set xmax [winfo width $path]
  1191. set ymax [winfo height $path]
  1192. set scroll {}
  1193. if { $y <= 6 } {
  1194. if { [lindex [$path.c yview] 0] > 0 } {
  1195. set scroll [list yview -1]
  1196. DropSite::setcursor sb_up_arrow
  1197. }
  1198. } elseif { $y >= $ymax-6 } {
  1199. if { [lindex [$path.c yview] 1] < 1 } {
  1200. set scroll [list yview 1]
  1201. DropSite::setcursor sb_down_arrow
  1202. }
  1203. } elseif { $x <= 6 } {
  1204. if { [lindex [$path.c xview] 0] > 0 } {
  1205. set scroll [list xview -1]
  1206. DropSite::setcursor sb_left_arrow
  1207. }
  1208. } elseif { $x >= $xmax-6 } {
  1209. if { [lindex [$path.c xview] 1] < 1 } {
  1210. set scroll [list xview 1]
  1211. DropSite::setcursor sb_right_arrow
  1212. }
  1213. }
  1214. if { [string length $data(dnd,afterid)] && ![string equal $data(dnd,scroll) $scroll] } {
  1215. after cancel $data(dnd,afterid)
  1216. set data(dnd,afterid) ""
  1217. }
  1218. set data(dnd,scroll) $scroll
  1219. if { [llength $scroll] && ![string length $data(dnd,afterid)] } {
  1220. set data(dnd,afterid) [after 200 ListBox::_scroll $path $scroll]
  1221. }
  1222. return $data(dnd,afterid)
  1223. }
  1224. # -----------------------------------------------------------------------------
  1225. # Command ListBox::_multiple_select
  1226. # -----------------------------------------------------------------------------
  1227. proc ListBox::_multiple_select { path mode x y idx } {
  1228. variable $path
  1229. upvar 0 $path data
  1230. if { ![info exists data(anchor)] || ![info exists data(sel_anchor)] } {
  1231. set data(anchor) $idx
  1232. set data(sel_anchor) {}
  1233. }
  1234. switch -exact -- $mode {
  1235. n {
  1236. _mouse_select $path set $idx
  1237. set data(anchor) $idx
  1238. set data(sel_anchor) {}
  1239. }
  1240. c {
  1241. set l [_mouse_select $path get]
  1242. if { [lsearch -exact $l $idx] >= 0 } {
  1243. _mouse_select $path remove $idx
  1244. } else {
  1245. _mouse_select $path add $idx
  1246. }
  1247. set data(anchor) $idx
  1248. set data(sel_anchor) {}
  1249. }
  1250. s {
  1251. eval [list $path _mouse_select remove] $data(sel_anchor)
  1252. set ix [$path index $idx]
  1253. set ia [$path index $data(anchor)]
  1254. if { $ix > $ia } {
  1255. set istart $ia
  1256. set iend $ix
  1257. } else {
  1258. set istart $ix
  1259. set iend $ia
  1260. }
  1261. for { set i $istart } { $i <= $iend } { incr i } {
  1262. set l [$path selection get]
  1263. set t [$path items $i]
  1264. set li [lsearch -exact $l $t]
  1265. if { $li < 0 } {
  1266. _mouse_select $path add $t
  1267. lappend data(sel_anchor) $t
  1268. }
  1269. }
  1270. }
  1271. }
  1272. }
  1273. # ----------------------------------------------------------------------------
  1274. # Command ListBox::_scroll
  1275. # ----------------------------------------------------------------------------
  1276. proc ListBox::_scroll { path cmd dir } {
  1277. variable $path
  1278. upvar 0 $path data
  1279. if { ($dir == -1 && [lindex [$path.c $cmd] 0] > 0) ||
  1280. ($dir == 1 && [lindex [$path.c $cmd] 1] < 1) } {
  1281. $path $cmd scroll $dir units
  1282. set data(dnd,afterid) [after 100 ListBox::_scroll $path $cmd $dir]
  1283. } else {
  1284. set data(dnd,afterid) ""
  1285. DropSite::setcursor dot
  1286. }
  1287. }
  1288. # ListBox::_set_help --
  1289. #
  1290. # Register dynamic help for an item in the listbox.
  1291. #
  1292. # Arguments:
  1293. # path ListBox to query
  1294. # item Item in the listbox
  1295. # force Optional argument to force a reset of the help
  1296. #
  1297. # Results:
  1298. # none
  1299. proc ListBox::_set_help { path node } {
  1300. Widget::getVariable $path help
  1301. set item $path.$node
  1302. set opts [list -helptype -helptext -helpvar]
  1303. foreach {cty ctx cv} [eval [list Widget::hasChangedX $item] $opts] break
  1304. set text [Widget::getoption $item -helptext]
  1305. ## If we've never set help for this item before, and text is not blank,
  1306. ## we need to setup help. We also need to reset help if any of the
  1307. ## options have changed.
  1308. if { (![info exists help($node)] && $text != "") || $cty || $ctx || $cv } {
  1309. set help($node) 1
  1310. set type [Widget::getoption $item -helptype]
  1311. switch $type {
  1312. balloon {
  1313. DynamicHelp::register $path.c balloon n:$node $text
  1314. DynamicHelp::register $path.c balloon i:$node $text
  1315. DynamicHelp::register $path.c balloon b:$node $text
  1316. }
  1317. variable {
  1318. set var [Widget::getoption $item -helpvar]
  1319. DynamicHelp::register $path.c variable n:$node $var $text
  1320. DynamicHelp::register $path.c variable i:$node $var $text
  1321. DynamicHelp::register $path.c variable b:$node $var $text
  1322. }
  1323. }
  1324. }
  1325. }
  1326. # ListBox::_mouse_select --
  1327. #
  1328. # Handle selection commands that are done by the mouse. If the
  1329. # selection command returns true, we generate a <<ListboxSelect>>
  1330. # event for the listbox.
  1331. #
  1332. # Arguments:
  1333. # Standard arguments passed to a selection command.
  1334. #
  1335. # Results:
  1336. # none
  1337. proc ListBox::_mouse_select { path cmd args } {
  1338. eval selection [list $path] [list $cmd] $args
  1339. switch -- $cmd {
  1340. "add" - "clear" - "remove" - "set" {
  1341. event generate $path <<Listbo

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