PageRenderTime 170ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://bitbucket.org/jmelo_lyncode/thesis
TCL | 736 lines | 505 code | 103 blank | 128 comment | 111 complexity | 1c5eba00b29734cadd4ca91043c4f66d MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-3.0
  1. # ----------------------------------------------------------------------------
  2. # combobox.tcl
  3. # This file is part of Unifix BWidget Toolkit
  4. # $Id: combobox.tcl,v 1.29 2003/11/06 05:49:44 damonc Exp $
  5. # ----------------------------------------------------------------------------
  6. # Index of commands:
  7. # - ComboBox::create
  8. # - ComboBox::configure
  9. # - ComboBox::cget
  10. # - ComboBox::setvalue
  11. # - ComboBox::getvalue
  12. # - ComboBox::_create_popup
  13. # - ComboBox::_mapliste
  14. # - ComboBox::_unmapliste
  15. # - ComboBox::_select
  16. # - ComboBox::_modify_value
  17. # ----------------------------------------------------------------------------
  18. # ComboBox uses the 8.3 -listvariable listbox option
  19. package require Tk 8.3
  20. namespace eval ComboBox {
  21. Widget::define ComboBox combobox ArrowButton Entry ListBox
  22. Widget::tkinclude ComboBox frame :cmd \
  23. include {-relief -borderwidth -bd -background} \
  24. initialize {-relief sunken -borderwidth 2} \
  25. Widget::bwinclude ComboBox Entry .e \
  26. remove {-relief -bd -borderwidth -bg} \
  27. rename {-background -entrybg}
  28. Widget::declare ComboBox {
  29. {-height TkResource 0 0 listbox}
  30. {-values String "" 0}
  31. {-images String "" 0}
  32. {-indents String "" 0}
  33. {-modifycmd String "" 0}
  34. {-postcommand String "" 0}
  35. {-expand Enum none 0 {none tab}}
  36. {-autocomplete Boolean 0 0}
  37. {-bwlistbox Boolean 0 0}
  38. {-listboxwidth Int 0 0}
  39. {-hottrack Boolean 0 0}
  40. }
  41. Widget::addmap ComboBox ArrowButton .a {
  42. -background {} -foreground {} -disabledforeground {} -state {}
  43. }
  44. Widget::syncoptions ComboBox Entry .e {-text {}}
  45. ::bind BwComboBox <FocusIn> [list after idle {BWidget::refocus %W %W.e}]
  46. ::bind BwComboBox <Destroy> [list Widget::destroy %W]
  47. ::bind ListBoxHotTrack <Motion> {
  48. %W selection clear 0 end
  49. %W activate @%x,%y
  50. %W selection set @%x,%y
  51. }
  52. }
  53. # ComboBox::create --
  54. #
  55. # Create a combobox widget with the given options.
  56. #
  57. # Arguments:
  58. # path name of the new widget.
  59. # args optional arguments to the widget.
  60. #
  61. # Results:
  62. # path name of the new widget.
  63. proc ComboBox::create { path args } {
  64. array set maps [list ComboBox {} :cmd {} .e {} .a {}]
  65. array set maps [Widget::parseArgs ComboBox $args]
  66. eval [list frame $path] $maps(:cmd) \
  67. [list -highlightthickness 0 -takefocus 0 -class ComboBox]
  68. Widget::initFromODB ComboBox $path $maps(ComboBox)
  69. bindtags $path [list $path BwComboBox [winfo toplevel $path] all]
  70. set entry [eval [list Entry::create $path.e] $maps(.e) \
  71. [list -relief flat -borderwidth 0 -takefocus 1]]
  72. ::bind $path.e <FocusOut> [list $path _focus_out]
  73. ::bind $path <<TraverseIn>> [list $path _traverse_in]
  74. if {[Widget::cget $path -autocomplete]} {
  75. ::bind $path.e <KeyRelease> [list $path _auto_complete %K]
  76. }
  77. if {[string equal $::tcl_platform(platform) "unix"]} {
  78. set ipadx 0
  79. set width 11
  80. } else {
  81. set ipadx 2
  82. set width 15
  83. }
  84. set height [winfo reqheight $entry]
  85. set arrow [eval [list ArrowButton::create $path.a] $maps(.a) \
  86. -width $width -height $height \
  87. -highlightthickness 0 -borderwidth 1 -takefocus 0 \
  88. -dir bottom \
  89. -type button \
  90. -ipadx $ipadx \
  91. -command [list [list ComboBox::_mapliste $path]]]
  92. pack $arrow -side right -fill y
  93. pack $entry -side left -fill both -expand yes
  94. set editable [Widget::cget $path -editable]
  95. Entry::configure $path.e -editable $editable
  96. if {$editable} {
  97. ::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
  98. } else {
  99. ::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
  100. if { ![string equal [Widget::cget $path -state] "disabled"] } {
  101. Entry::configure $path.e -takefocus 1
  102. }
  103. }
  104. ::bind $path <ButtonPress-1> [list ComboBox::_unmapliste $path]
  105. ::bind $entry <Key-Up> [list ComboBox::_unmapliste $path]
  106. ::bind $entry <Key-Down> [list ComboBox::_mapliste $path]
  107. ::bind $entry <Control-Up> [list ComboBox::_modify_value $path previous]
  108. ::bind $entry <Control-Down> [list ComboBox::_modify_value $path next]
  109. ::bind $entry <Control-Prior> [list ComboBox::_modify_value $path first]
  110. ::bind $entry <Control-Next> [list ComboBox::_modify_value $path last]
  111. if {$editable} {
  112. set expand [Widget::cget $path -expand]
  113. if {[string equal "tab" $expand]} {
  114. # Expand entry value on Tab (from -values)
  115. ::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
  116. } elseif {[string equal "auto" $expand]} {
  117. # Expand entry value anytime (from -values)
  118. #::bind $entry <Key> "[list ComboBox::_expand $path]; break"
  119. }
  120. }
  121. ## If we have images, we have to use a BWidget ListBox.
  122. set bw [Widget::cget $path -bwlistbox]
  123. if {[llength [Widget::cget $path -images]]} {
  124. Widget::configure $path [list -bwlistbox 1]
  125. } else {
  126. Widget::configure $path [list -bwlistbox $bw]
  127. }
  128. return [Widget::create ComboBox $path]
  129. }
  130. # ComboBox::configure --
  131. #
  132. # Configure subcommand for ComboBox widgets. Works like regular
  133. # widget configure command.
  134. #
  135. # Arguments:
  136. # path Name of the ComboBox widget.
  137. # args Additional optional arguments:
  138. # ?-option?
  139. # ?-option value ...?
  140. #
  141. # Results:
  142. # Depends on arguments. If no arguments are given, returns a complete
  143. # list of configuration information. If one argument is given, returns
  144. # the configuration information for that option. If more than one
  145. # argument is given, returns nothing.
  146. proc ComboBox::configure { path args } {
  147. set res [Widget::configure $path $args]
  148. set entry $path.e
  149. set list [list -images -values -bwlistbox -hottrack]
  150. foreach {ci cv cb ch} [eval Widget::hasChangedX $path $list] { break }
  151. if { $ci } {
  152. set images [Widget::cget $path -images]
  153. if {[llength $images]} {
  154. Widget::configure $path [list -bwlistbox 1]
  155. } else {
  156. Widget::configure $path [list -bwlistbox 0]
  157. }
  158. }
  159. set bw [Widget::cget $path -bwlistbox]
  160. ## If the images, bwlistbox, hottrack or values have changed,
  161. ## destroy the shell so that it will re-create itself the next
  162. ## time around.
  163. if { $ci || $cb || $ch || ($bw && $cv) } {
  164. destroy $path.shell
  165. }
  166. set chgedit [Widget::hasChangedX $path -editable]
  167. if {$chgedit} {
  168. if {[Widget::cget $path -editable]} {
  169. ::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
  170. Entry::configure $entry -editable true
  171. } else {
  172. ::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
  173. Entry::configure $entry -editable false
  174. # Make sure that non-editable comboboxes can still be tabbed to.
  175. if { ![string equal [Widget::cget $path -state] "disabled"] } {
  176. Entry::configure $entry -takefocus 1
  177. }
  178. }
  179. }
  180. if {$chgedit || [Widget::hasChangedX $path -expand]} {
  181. # Unset what we may have created.
  182. ::bind $entry <Tab> {}
  183. if {[Widget::cget $path -editable]} {
  184. set expand [Widget::cget $path -expand]
  185. if {[string equal "tab" $expand]} {
  186. # Expand entry value on Tab (from -values)
  187. ::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
  188. } elseif {[string equal "auto" $expand]} {
  189. # Expand entry value anytime (from -values)
  190. #::bind $entry <Key> "[list ComboBox::_expand $path]; break"
  191. }
  192. }
  193. }
  194. # if the dropdown listbox is shown, simply force the actual entry
  195. # colors into it. If it is not shown, the next time the dropdown
  196. # is shown it'll get the actual colors anyway
  197. if {[winfo exists $path.shell.listb]} {
  198. $path.shell.listb configure \
  199. -bg [Widget::cget $path -entrybg] \
  200. -fg [Widget::cget $path -foreground] \
  201. -selectbackground [Widget::cget $path -selectbackground] \
  202. -selectforeground [Widget::cget $path -selectforeground]
  203. }
  204. return $res
  205. }
  206. # ----------------------------------------------------------------------------
  207. # Command ComboBox::cget
  208. # ----------------------------------------------------------------------------
  209. proc ComboBox::cget { path option } {
  210. return [Widget::cget $path $option]
  211. }
  212. # ----------------------------------------------------------------------------
  213. # Command ComboBox::setvalue
  214. # ----------------------------------------------------------------------------
  215. proc ComboBox::setvalue { path index } {
  216. set values [Widget::getMegawidgetOption $path -values]
  217. set value [Entry::cget $path.e -text]
  218. switch -- $index {
  219. next {
  220. if { [set idx [lsearch -exact $values $value]] != -1 } {
  221. incr idx
  222. } else {
  223. set idx [lsearch -exact $values "$value*"]
  224. }
  225. }
  226. previous {
  227. if { [set idx [lsearch -exact $values $value]] != -1 } {
  228. incr idx -1
  229. } else {
  230. set idx [lsearch -exact $values "$value*"]
  231. }
  232. }
  233. first {
  234. set idx 0
  235. }
  236. last {
  237. set idx [expr {[llength $values]-1}]
  238. }
  239. default {
  240. if { [string index $index 0] == "@" } {
  241. set idx [string range $index 1 end]
  242. if { ![string is integer -strict $idx] } {
  243. return -code error "bad index \"$index\""
  244. }
  245. } else {
  246. return -code error "bad index \"$index\""
  247. }
  248. }
  249. }
  250. if { $idx >= 0 && $idx < [llength $values] } {
  251. set newval [lindex $values $idx]
  252. Entry::configure $path.e -text $newval
  253. return 1
  254. }
  255. return 0
  256. }
  257. proc ComboBox::icursor { path idx } {
  258. return [$path.e icursor $idx]
  259. }
  260. proc ComboBox::get { path } {
  261. return [$path.e get]
  262. }
  263. # ----------------------------------------------------------------------------
  264. # Command ComboBox::getvalue
  265. # ----------------------------------------------------------------------------
  266. proc ComboBox::getvalue { path } {
  267. set values [Widget::getMegawidgetOption $path -values]
  268. set value [Entry::cget $path.e -text]
  269. return [lsearch -exact $values $value]
  270. }
  271. proc ComboBox::getlistbox { path } {
  272. _create_popup $path
  273. return $path.shell.listb
  274. }
  275. # ----------------------------------------------------------------------------
  276. # Command ComboBox::post
  277. # ----------------------------------------------------------------------------
  278. proc ComboBox::post { path } {
  279. _mapliste $path
  280. return
  281. }
  282. proc ComboBox::unpost { path } {
  283. _unmapliste $path
  284. return
  285. }
  286. # ----------------------------------------------------------------------------
  287. # Command ComboBox::bind
  288. # ----------------------------------------------------------------------------
  289. proc ComboBox::bind { path args } {
  290. return [eval [list ::bind $path.e] $args]
  291. }
  292. proc ComboBox::insert { path idx args } {
  293. upvar #0 [Widget::varForOption $path -values] values
  294. if {[Widget::cget $path -bwlistbox]} {
  295. set l [$path getlistbox]
  296. set i [eval $l insert $idx #auto $args]
  297. set text [$l itemcget $i -text]
  298. if {$idx == "end"} {
  299. lappend values $text
  300. } else {
  301. set values [linsert $values $idx $text]
  302. }
  303. } else {
  304. set values [eval linsert [list $values] $idx $args]
  305. }
  306. }
  307. # ----------------------------------------------------------------------------
  308. # Command ComboBox::_create_popup
  309. # ----------------------------------------------------------------------------
  310. proc ComboBox::_create_popup { path } {
  311. set shell $path.shell
  312. if {[winfo exists $shell]} { return }
  313. set lval [Widget::cget $path -values]
  314. set h [Widget::cget $path -height]
  315. set bw [Widget::cget $path -bwlistbox]
  316. if { $h <= 0 } {
  317. set len [llength $lval]
  318. if { $len < 3 } {
  319. set h 3
  320. } elseif { $len > 10 } {
  321. set h 10
  322. } else {
  323. set h $len
  324. }
  325. }
  326. if { $::tcl_platform(platform) == "unix" } {
  327. set sbwidth 11
  328. } else {
  329. set sbwidth 15
  330. }
  331. toplevel $shell -relief solid -bd 1
  332. wm withdraw $shell
  333. update idletasks
  334. wm overrideredirect $shell 1
  335. wm transient $shell [winfo toplevel $path]
  336. wm withdraw $shell
  337. catch { wm attributes $shell -topmost 1 }
  338. set sw [ScrolledWindow $shell.sw -managed 0 -size $sbwidth -ipad 0]
  339. if {$bw} {
  340. set listb [ListBox $shell.listb \
  341. -relief flat -borderwidth 0 -highlightthickness 0 \
  342. -selectmode single -selectfill 1 -autofocus 0 -height $h \
  343. -font [Widget::cget $path -font] \
  344. -bg [Widget::cget $path -entrybg] \
  345. -fg [Widget::cget $path -foreground] \
  346. -selectbackground [Widget::cget $path -selectbackground] \
  347. -selectforeground [Widget::cget $path -selectforeground]]
  348. set values [Widget::cget $path -values]
  349. set images [Widget::cget $path -images]
  350. foreach value $values image $images {
  351. $listb insert end #auto -text $value -image $image
  352. }
  353. $listb bindText <1> "ComboBox::_select $path"
  354. $listb bindImage <1> "ComboBox::_select $path"
  355. if {[Widget::cget $path -hottrack]} {
  356. $listb bindText <Enter> [list $listb selection set]
  357. $listb bindImage <Enter> [list $listb selection set]
  358. }
  359. } else {
  360. set listb [listbox $shell.listb \
  361. -relief flat -borderwidth 0 -highlightthickness 0 \
  362. -exportselection false \
  363. -font [Widget::cget $path -font] \
  364. -height $h \
  365. -bg [Widget::cget $path -entrybg] \
  366. -fg [Widget::cget $path -foreground] \
  367. -selectbackground [Widget::cget $path -selectbackground] \
  368. -selectforeground [Widget::cget $path -selectforeground] \
  369. -listvariable [Widget::varForOption $path -values]]
  370. ::bind $listb <ButtonRelease-1> [list ComboBox::_select $path @%x,%y]
  371. if {[Widget::cget $path -hottrack]} {
  372. bindtags $listb [concat [bindtags $listb] ListBoxHotTrack]
  373. }
  374. }
  375. pack $sw -fill both -expand yes
  376. $sw setwidget $listb
  377. ::bind $listb <Return> "ComboBox::_select $path \[%W curselection]"
  378. ::bind $listb <Escape> [list ComboBox::_unmapliste $path]
  379. ::bind $listb <FocusOut> [list ComboBox::_focus_out $path]
  380. }
  381. proc ComboBox::_recreate_popup { path } {
  382. variable background
  383. variable foreground
  384. set shell $path.shell
  385. set lval [Widget::cget $path -values]
  386. set h [Widget::cget $path -height]
  387. set bw [Widget::cget $path -bwlistbox]
  388. if { $h <= 0 } {
  389. set len [llength $lval]
  390. if { $len < 3 } {
  391. set h 3
  392. } elseif { $len > 10 } {
  393. set h 10
  394. } else {
  395. set h $len
  396. }
  397. }
  398. if { $::tcl_platform(platform) == "unix" } {
  399. set sbwidth 11
  400. } else {
  401. set sbwidth 15
  402. }
  403. _create_popup $path
  404. if {![Widget::cget $path -editable]} {
  405. if {[info exists background]} {
  406. $path.e configure -bg $background
  407. $path.e configure -fg $foreground
  408. unset background
  409. unset foreground
  410. }
  411. }
  412. set listb $shell.listb
  413. destroy $shell.sw
  414. set sw [ScrolledWindow $shell.sw -managed 0 -size $sbwidth -ipad 0]
  415. $listb configure \
  416. -height $h \
  417. -font [Widget::cget $path -font] \
  418. -bg [Widget::cget $path -entrybg] \
  419. -fg [Widget::cget $path -foreground] \
  420. -selectbackground [Widget::cget $path -selectbackground] \
  421. -selectforeground [Widget::cget $path -selectforeground]
  422. pack $sw -fill both -expand yes
  423. $sw setwidget $listb
  424. raise $listb
  425. }
  426. # ----------------------------------------------------------------------------
  427. # Command ComboBox::_mapliste
  428. # ----------------------------------------------------------------------------
  429. proc ComboBox::_mapliste { path } {
  430. set listb $path.shell.listb
  431. if {[winfo exists $path.shell] &&
  432. [string equal [wm state $path.shell] "normal"]} {
  433. _unmapliste $path
  434. return
  435. }
  436. if { [Widget::cget $path -state] == "disabled" } {
  437. return
  438. }
  439. if { [set cmd [Widget::getMegawidgetOption $path -postcommand]] != "" } {
  440. uplevel \#0 $cmd
  441. }
  442. if { ![llength [Widget::getMegawidgetOption $path -values]] } {
  443. return
  444. }
  445. _recreate_popup $path
  446. ArrowButton::configure $path.a -relief sunken
  447. update
  448. set bw [Widget::cget $path -bwlistbox]
  449. $listb selection clear 0 end
  450. set values [Widget::getMegawidgetOption $path -values]
  451. set curval [Entry::cget $path.e -text]
  452. if { [set idx [lsearch -exact $values $curval]] != -1 ||
  453. [set idx [lsearch -exact $values "$curval*"]] != -1 } {
  454. if {$bw} {
  455. set idx [$listb items $idx]
  456. } else {
  457. $listb activate $idx
  458. }
  459. $listb selection set $idx
  460. $listb see $idx
  461. } else {
  462. set idx 0
  463. if {$bw} {
  464. set idx [$listb items 0]
  465. } else {
  466. $listb activate $idx
  467. }
  468. $listb selection set $idx
  469. $listb see $idx
  470. }
  471. set width [Widget::cget $path -listboxwidth]
  472. if {!$width} { set width [winfo width $path] }
  473. BWidget::place $path.shell $width 0 below $path
  474. wm deiconify $path.shell
  475. raise $path.shell
  476. BWidget::focus set $listb
  477. BWidget::grab global $path
  478. }
  479. # ----------------------------------------------------------------------------
  480. # Command ComboBox::_unmapliste
  481. # ----------------------------------------------------------------------------
  482. proc ComboBox::_unmapliste { path {refocus 1} } {
  483. if {[winfo exists $path.shell] && \
  484. [string equal [wm state $path.shell] "normal"]} {
  485. BWidget::grab release $path
  486. BWidget::focus release $path.shell.listb $refocus
  487. # Update now because otherwise [focus -force...] makes the app hang!
  488. if {$refocus} {
  489. update
  490. focus -force $path.e
  491. }
  492. wm withdraw $path.shell
  493. ArrowButton::configure $path.a -relief raised
  494. }
  495. }
  496. # ----------------------------------------------------------------------------
  497. # Command ComboBox::_select
  498. # ----------------------------------------------------------------------------
  499. proc ComboBox::_select { path index } {
  500. set index [$path.shell.listb index $index]
  501. _unmapliste $path
  502. if { $index != -1 } {
  503. if { [setvalue $path @$index] } {
  504. set cmd [Widget::getMegawidgetOption $path -modifycmd]
  505. if { $cmd != "" } {
  506. uplevel \#0 $cmd
  507. }
  508. }
  509. }
  510. $path.e selection clear
  511. $path.e selection range 0 end
  512. }
  513. # ----------------------------------------------------------------------------
  514. # Command ComboBox::_modify_value
  515. # ----------------------------------------------------------------------------
  516. proc ComboBox::_modify_value { path direction } {
  517. if { [setvalue $path $direction] } {
  518. if { [set cmd [Widget::getMegawidgetOption $path -modifycmd]] != "" } {
  519. uplevel \#0 $cmd
  520. }
  521. }
  522. }
  523. # ----------------------------------------------------------------------------
  524. # Command ComboBox::_expand
  525. # ----------------------------------------------------------------------------
  526. proc ComboBox::_expand {path} {
  527. set values [Widget::getMegawidgetOption $path -values]
  528. if {![llength $values]} {
  529. bell
  530. return 0
  531. }
  532. set found {}
  533. set curval [Entry::cget $path.e -text]
  534. set curlen [$path.e index insert]
  535. if {$curlen < [string length $curval]} {
  536. # we are somewhere in the middle of a string.
  537. # if the full value matches some string in the listbox,
  538. # reorder values to start matching after that string.
  539. set idx [lsearch -exact $values $curval]
  540. if {$idx >= 0} {
  541. set values [concat [lrange $values [expr {$idx+1}] end] \
  542. [lrange $values 0 $idx]]
  543. }
  544. }
  545. if {$curlen == 0} {
  546. set found $values
  547. } else {
  548. foreach val $values {
  549. if {[string equal -length $curlen $curval $val]} {
  550. lappend found $val
  551. }
  552. }
  553. }
  554. if {[llength $found]} {
  555. Entry::configure $path.e -text [lindex $found 0]
  556. if {[llength $found] > 1} {
  557. set best [_best_match $found [string range $curval 0 $curlen]]
  558. set blen [string length $best]
  559. $path.e icursor $blen
  560. $path.e selection range $blen end
  561. }
  562. } else {
  563. bell
  564. }
  565. return [llength $found]
  566. }
  567. # best_match --
  568. # finds the best unique match in a list of names
  569. # The extra $e in this argument allows us to limit the innermost loop a
  570. # little further.
  571. # Arguments:
  572. # l list to find best unique match in
  573. # e currently best known unique match
  574. # Returns:
  575. # longest unique match in the list
  576. #
  577. proc ComboBox::_best_match {l {e {}}} {
  578. set ec [lindex $l 0]
  579. if {[llength $l]>1} {
  580. set e [string length $e]; incr e -1
  581. set ei [string length $ec]; incr ei -1
  582. foreach l $l {
  583. while {$ei>=$e && [string first $ec $l]} {
  584. set ec [string range $ec 0 [incr ei -1]]
  585. }
  586. }
  587. }
  588. return $ec
  589. }
  590. # possibly faster
  591. #proc match {string1 string2} {
  592. # set i 1
  593. # while {[string equal -length $i $string1 $string2]} { incr i }
  594. # return [string range $string1 0 [expr {$i-2}]]
  595. #}
  596. #proc matchlist {list} {
  597. # set list [lsort $list]
  598. # return [match [lindex $list 0] [lindex $list end]]
  599. #}
  600. # ----------------------------------------------------------------------------
  601. # Command ComboBox::_traverse_in
  602. # Called when widget receives keyboard focus due to keyboard traversal.
  603. # ----------------------------------------------------------------------------
  604. proc ComboBox::_traverse_in { path } {
  605. if {[$path.e selection present] != 1} {
  606. # Autohighlight the selection, but not if one existed
  607. $path.e selection range 0 end
  608. }
  609. }
  610. # ----------------------------------------------------------------------------
  611. # Command ComboBox::_focus_out
  612. # ----------------------------------------------------------------------------
  613. proc ComboBox::_focus_out { path } {
  614. if {[focus] == ""} {
  615. # we lost focus to some other app, make sure we drop the listbox
  616. return [_unmapliste $path 0]
  617. }
  618. }
  619. proc ComboBox::_auto_complete { path key } {
  620. ## Anything that is all lowercase is either a letter, number
  621. ## or special key we're ok with. Everything else is a
  622. ## functional key of some kind.
  623. if {[string tolower $key] != $key} { return }
  624. set text [string map [list {[} {\[} {]} {\]}] [$path.e get]]
  625. if {[string equal $text ""]} { return }
  626. set values [Widget::cget $path -values]
  627. set x [lsearch $values $text*]
  628. if {$x < 0} { return }
  629. set idx [$path.e index insert]
  630. $path.e configure -text [lindex $values $x]
  631. $path.e icursor $idx
  632. $path.e select range insert end
  633. }