ComboBox.tcl 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558
  1. # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
  2. #
  3. # $Id: ComboBox.tcl,v 1.9 2008/02/28 22:39:13 hobbs Exp $
  4. #
  5. # tixCombobox --
  6. #
  7. # A combobox widget is basically a listbox widget with an entry
  8. # widget.
  9. #
  10. #
  11. # Copyright (c) 1993-1999 Ioi Kim Lam.
  12. # Copyright (c) 2000-2001 Tix Project Group.
  13. # Copyright (c) 2004 ActiveState
  14. #
  15. # See the file "license.terms" for information on usage and redistribution
  16. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  17. global tkPriv
  18. if {![llength [info globals tkPriv]]} {
  19. tk::unsupported::ExposePrivateVariable tkPriv
  20. }
  21. #--------------------------------------------------------------------------
  22. # tkPriv elements used in this file:
  23. #
  24. # afterId - Token returned by "after" for autoscanning.
  25. #--------------------------------------------------------------------------
  26. #
  27. foreach fun {tkCancelRepeat tkListboxUpDown tkButtonUp} {
  28. if {![llength [info commands $fun]]} {
  29. tk::unsupported::ExposePrivateCommand $fun
  30. }
  31. }
  32. unset fun
  33. tixWidgetClass tixComboBox {
  34. -classname TixComboBox
  35. -superclass tixLabelWidget
  36. -method {
  37. addhistory align appendhistory flash invoke insert pick popdown
  38. }
  39. -flag {
  40. -anchor -arrowbitmap -browsecmd -command -crossbitmap
  41. -disablecallback -disabledforeground -dropdown -editable
  42. -fancy -grab -histlimit -historylimit -history -listcmd
  43. -listwidth -prunehistory -selection -selectmode -state
  44. -tickbitmap -validatecmd -value -variable
  45. }
  46. -static {
  47. -dropdown -fancy
  48. }
  49. -forcecall {
  50. -variable -selectmode -state
  51. }
  52. -configspec {
  53. {-arrowbitmap arrowBitmap ArrowBitmap ""}
  54. {-anchor anchor Anchor w}
  55. {-browsecmd browseCmd BrowseCmd ""}
  56. {-command command Command ""}
  57. {-crossbitmap crossBitmap CrossBitmap ""}
  58. {-disablecallback disableCallback DisableCallback 0 tixVerifyBoolean}
  59. {-disabledforeground disabledForeground DisabledForeground #606060}
  60. {-dropdown dropDown DropDown true tixVerifyBoolean}
  61. {-editable editable Editable false tixVerifyBoolean}
  62. {-fancy fancy Fancy false tixVerifyBoolean}
  63. {-grab grab Grab global}
  64. {-listcmd listCmd ListCmd ""}
  65. {-listwidth listWidth ListWidth ""}
  66. {-historylimit historyLimit HistoryLimit ""}
  67. {-history history History false tixVerifyBoolean}
  68. {-prunehistory pruneHistory PruneHistory true tixVerifyBoolean}
  69. {-selectmode selectMode SelectMode browse}
  70. {-selection selection Selection ""}
  71. {-state state State normal}
  72. {-validatecmd validateCmd ValidateCmd ""}
  73. {-value value Value ""}
  74. {-variable variable Variable ""}
  75. {-tickbitmap tickBitmap TickBitmap ""}
  76. }
  77. -alias {
  78. {-histlimit -historylimit}
  79. }
  80. -default {
  81. {*Entry.relief sunken}
  82. {*TixScrolledListBox.scrollbar auto}
  83. {*Listbox.exportSelection false}
  84. {*Listbox.takeFocus false}
  85. {*shell.borderWidth 2}
  86. {*shell.relief raised}
  87. {*shell.cursor arrow}
  88. {*Button.anchor c}
  89. {*Button.borderWidth 1}
  90. {*Button.highlightThickness 0}
  91. {*Button.padX 0}
  92. {*Button.padY 0}
  93. {*tick.width 18}
  94. {*tick.height 18}
  95. {*cross.width 18}
  96. {*cross.height 18}
  97. {*arrow.anchor c}
  98. {*arrow.width 15}
  99. {*arrow.height 18}
  100. }
  101. }
  102. # States: normal numbers: for dropdown style
  103. # d+digit(s) : for non-dropdown style
  104. #
  105. proc tixComboBox:InitWidgetRec {w} {
  106. upvar #0 $w data
  107. tixChainMethod $w InitWidgetRec
  108. set data(curIndex) ""
  109. set data(varInited) 0
  110. set data(state) none
  111. set data(ignore) 0
  112. if {$data(-history)} {
  113. set data(-editable) 1
  114. }
  115. if {$data(-arrowbitmap) eq ""} {
  116. set data(-arrowbitmap) [tix getbitmap cbxarrow]
  117. }
  118. if {$data(-crossbitmap) eq ""} {
  119. set data(-crossbitmap) [tix getbitmap cross]
  120. }
  121. if {$data(-tickbitmap) eq ""} {
  122. set data(-tickbitmap) [tix getbitmap tick]
  123. }
  124. }
  125. proc tixComboBox:ConstructFramedWidget {w frame} {
  126. upvar #0 $w data
  127. tixChainMethod $w ConstructFramedWidget $frame
  128. if {$data(-dropdown)} {
  129. tixComboBox:ConstructEntryFrame $w $frame
  130. tixComboBox:ConstructListShell $w
  131. } else {
  132. set f1 [frame $frame.f1]
  133. set f2 [frame $frame.f2]
  134. tixComboBox:ConstructEntryFrame $w $f1
  135. tixComboBox:ConstructListFrame $w $f2
  136. pack $f1 -side top -pady 2 -fill x
  137. pack $f2 -side top -pady 2 -fill both -expand yes
  138. }
  139. }
  140. proc tixComboBox:ConstructEntryFrame {w frame} {
  141. upvar #0 $w data
  142. # (1) The entry
  143. #
  144. set data(w:entry) [entry $frame.entry]
  145. if {!$data(-editable)} {
  146. set bg [$w cget -bg]
  147. $data(w:entry) config -bg $bg -state disabled -takefocus 1
  148. }
  149. # This is used during "config-state"
  150. #
  151. set data(entryfg) [$data(w:entry) cget -fg]
  152. # (2) The dropdown button, not necessary when not in dropdown mode
  153. #
  154. set data(w:arrow) [button $frame.arrow -bitmap $data(-arrowbitmap)]
  155. if {!$data(-dropdown)} {
  156. set xframe [frame $frame.xframe -width 19]
  157. }
  158. # (3) The fancy tick and cross buttons
  159. #
  160. if {$data(-fancy)} {
  161. if {$data(-editable)} {
  162. set data(w:cross) [button $frame.cross -bitmap $data(-crossbitmap)]
  163. set data(w:tick) [button $frame.tick -bitmap $data(-tickbitmap)]
  164. pack $frame.cross -side left -padx 1
  165. pack $frame.tick -side left -padx 1
  166. } else {
  167. set data(w:tick) [button $frame.tick -bitmap $data(-tickbitmap)]
  168. pack $frame.tick -side left -padx 1
  169. }
  170. }
  171. if {$data(-dropdown)} {
  172. pack $data(w:arrow) -side right -padx 1
  173. foreach wid [list $data(w:frame) $data(w:label)] {
  174. tixAddBindTag $wid TixComboWid
  175. tixSetMegaWidget $wid $w TixComboBox
  176. }
  177. } else {
  178. pack $xframe -side right -padx 1
  179. }
  180. pack $frame.entry -side right -fill x -expand yes -padx 1
  181. }
  182. proc tixComboBox:ConstructListShell {w} {
  183. upvar #0 $w data
  184. # Create the shell and the list
  185. #------------------------------
  186. set data(w:shell) [menu $w.shell -bd 2 -relief raised -tearoff 0]
  187. wm overrideredirect $data(w:shell) 1
  188. wm withdraw $data(w:shell)
  189. set data(w:slistbox) [tixScrolledListBox $data(w:shell).slistbox \
  190. -anchor $data(-anchor) -scrollbarspace y \
  191. -options {listbox.selectMode "browse"}]
  192. set data(w:listbox) [$data(w:slistbox) subwidget listbox]
  193. pack $data(w:slistbox) -expand yes -fill both -padx 2 -pady 2
  194. }
  195. proc tixComboBox:ConstructListFrame {w frame} {
  196. upvar #0 $w data
  197. set data(w:slistbox) [tixScrolledListBox $frame.slistbox \
  198. -anchor $data(-anchor)]
  199. set data(w:listbox) [$data(w:slistbox) subwidget listbox]
  200. pack $data(w:slistbox) -expand yes -fill both
  201. }
  202. proc tixComboBox:SetBindings {w} {
  203. upvar #0 $w data
  204. tixChainMethod $w SetBindings
  205. # (1) Fix the bindings for the combobox
  206. #
  207. bindtags $w [list $w TixComboBox [winfo toplevel $w] all]
  208. # (2) The entry subwidget
  209. #
  210. tixSetMegaWidget $data(w:entry) $w TixComboBox
  211. bindtags $data(w:entry) [list $data(w:entry) Entry TixComboEntry\
  212. TixComboWid [winfo toplevel $data(w:entry)] all]
  213. # (3) The listbox and slistbox
  214. #
  215. $data(w:slistbox) config -browsecmd \
  216. [list tixComboBox:LbBrowse $w]
  217. $data(w:slistbox) config -command\
  218. [list tixComboBox:LbCommand $w]
  219. $data(w:listbox) config -takefocus 0
  220. tixAddBindTag $data(w:listbox) TixComboLb
  221. tixAddBindTag $data(w:slistbox) TixComboLb
  222. tixSetMegaWidget $data(w:listbox) $w TixComboBox
  223. tixSetMegaWidget $data(w:slistbox) $w TixComboBox
  224. # (4) The buttons
  225. #
  226. if {$data(-dropdown)} {
  227. $data(w:arrow) config -takefocus 0
  228. tixAddBindTag $data(w:arrow) TixComboArrow
  229. tixSetMegaWidget $data(w:arrow) $w TixComboBox
  230. bind $data(w:root) <1> [list tixComboBox:RootDown $w]
  231. bind $data(w:root) <ButtonRelease-1> [list tixComboBox:RootUp $w]
  232. }
  233. if {$data(-fancy)} {
  234. if {$data(-editable)} {
  235. $data(w:cross) config -command [list tixComboBox:CrossBtn $w] \
  236. -takefocus 0
  237. }
  238. $data(w:tick) config -command [list tixComboBox:Invoke $w] -takefocus 0
  239. }
  240. if {$data(-dropdown)} {
  241. set data(state) 0
  242. } else {
  243. set data(state) n0
  244. }
  245. }
  246. proc tixComboBoxBind {} {
  247. #----------------------------------------------------------------------
  248. # The class bindings for the TixComboBox
  249. #
  250. tixBind TixComboBox <Escape> {
  251. if {[tixComboBox:EscKey %W]} {
  252. break
  253. }
  254. }
  255. tixBind TixComboBox <Configure> {
  256. tixWidgetDoWhenIdle tixComboBox:align %W
  257. }
  258. # Only the two "linear" detail_fields are for tabbing (moving) among
  259. # widgets inside the same toplevel. Other detail_fields are sort
  260. # of irrelevant
  261. #
  262. tixBind TixComboBox <FocusOut> {
  263. if {[string equal %d NotifyNonlinear] ||
  264. [string equal %d NotifyNonlinearVirtual]} {
  265. if {[info exists %W(cancelTab)]} {
  266. unset %W(cancelTab)
  267. } else {
  268. if {[set %W(-state)] ne "disabled"} {
  269. if {[set %W(-selection)] ne [set %W(-value)]} {
  270. tixComboBox:Invoke %W
  271. }
  272. }
  273. }
  274. }
  275. }
  276. tixBind TixComboBox <FocusIn> {
  277. if {"%d" eq "NotifyNonlinear" || "%d" eq "NotifyNonlinearVirtual"} {
  278. focus [%W subwidget entry]
  279. # CYGNUS: Setting the selection if there is no data
  280. # causes backspace to misbehave.
  281. if {[[set %W(w:entry)] get] ne ""} {
  282. [set %W(w:entry)] selection from 0
  283. [set %W(w:entry)] selection to end
  284. }
  285. }
  286. }
  287. #----------------------------------------------------------------------
  288. # The class tixBindings for the arrow button widget inside the TixComboBox
  289. #
  290. tixBind TixComboArrow <1> {
  291. tixComboBox:ArrowDown [tixGetMegaWidget %W TixComboBox]
  292. }
  293. tixBind TixComboArrow <ButtonRelease-1> {
  294. tixComboBox:ArrowUp [tixGetMegaWidget %W TixComboBox]
  295. }
  296. tixBind TixComboArrow <Escape> {
  297. if {[tixComboBox:EscKey [tixGetMegaWidget %W TixComboBox]]} {
  298. break
  299. }
  300. }
  301. #----------------------------------------------------------------------
  302. # The class tixBindings for the entry widget inside the TixComboBox
  303. #
  304. tixBind TixComboEntry <Up> {
  305. tixComboBox:EntDirKey [tixGetMegaWidget %W TixComboBox] up
  306. }
  307. tixBind TixComboEntry <Down> {
  308. tixComboBox:EntDirKey [tixGetMegaWidget %W TixComboBox] down
  309. }
  310. tixBind TixComboEntry <Prior> {
  311. tixComboBox:EntDirKey [tixGetMegaWidget %W TixComboBox] pageup
  312. }
  313. tixBind TixComboEntry <Next> {
  314. tixComboBox:EntDirKey [tixGetMegaWidget %W TixComboBox] pagedown
  315. }
  316. tixBind TixComboEntry <Return> {
  317. tixComboBox:EntReturnKey [tixGetMegaWidget %W TixComboBox]
  318. }
  319. tixBind TixComboEntry <KeyPress> {
  320. tixComboBox:EntKeyPress [tixGetMegaWidget %W TixComboBox]
  321. }
  322. tixBind TixComboEntry <Escape> {
  323. if {[tixComboBox:EscKey [tixGetMegaWidget %W TixComboBox]]} {
  324. break
  325. }
  326. }
  327. tixBind TixComboEntry <Tab> {
  328. if {[set [tixGetMegaWidget %W TixComboBox](-state)] ne "disabled"} {
  329. if {[tixComboBox:EntTab [tixGetMegaWidget %W TixComboBox]]} {
  330. break
  331. }
  332. }
  333. }
  334. tixBind TixComboEntry <1> {
  335. if {[set [tixGetMegaWidget %W TixComboBox](-state)] ne "disabled"} {
  336. focus %W
  337. }
  338. }
  339. tixBind TixComboEntry <ButtonRelease-2> {
  340. tixComboBox:EntKeyPress [tixGetMegaWidget %W TixComboBox]
  341. }
  342. #----------------------------------------------------------------------
  343. # The class bindings for the listbox subwidget
  344. #
  345. tixBind TixComboWid <Escape> {
  346. if {[tixComboBox:EscKey [tixGetMegaWidget %W TixComboBox]]} {
  347. break
  348. }
  349. }
  350. #----------------------------------------------------------------------
  351. # The class bindings for some widgets inside ComboBox
  352. #
  353. tixBind TixComboWid <ButtonRelease-1> {
  354. tixComboBox:WidUp [tixGetMegaWidget %W TixComboBox]
  355. }
  356. tixBind TixComboWid <Escape> {
  357. if {[tixComboBox:EscKey [tixGetMegaWidget %W TixComboBox]]} {
  358. break
  359. }
  360. }
  361. }
  362. #----------------------------------------------------------------------
  363. # Cooked events
  364. #----------------------------------------------------------------------
  365. proc tixComboBox:ArrowDown {w} {
  366. upvar #0 $w data
  367. if {$data(-state) eq "disabled"} {
  368. return
  369. }
  370. switch -exact -- $data(state) {
  371. 0 { tixComboBox:GoState 1 $w }
  372. 2 { tixComboBox:GoState 19 $w }
  373. default { tixComboBox:StateError $w }
  374. }
  375. }
  376. proc tixComboBox:ArrowUp {w} {
  377. upvar #0 $w data
  378. switch -exact -- $data(state) {
  379. 1 { tixComboBox:GoState 2 $w }
  380. 19 {
  381. # data(ignore) was already set in state 19
  382. tixComboBox:GoState 4 $w
  383. }
  384. 5 { tixComboBox:GoState 13 $w }
  385. default { tixComboBox:StateError $w }
  386. }
  387. }
  388. proc tixComboBox:RootDown {w} {
  389. upvar #0 $w data
  390. switch -exact -- $data(state) {
  391. 0 {
  392. # Ignore
  393. }
  394. 2 { tixComboBox:GoState 3 $w }
  395. default { tixComboBox:StateError $w }
  396. }
  397. }
  398. proc tixComboBox:RootUp {w} {
  399. upvar #0 $w data
  400. switch -exact -- $data(state) {
  401. {1} {
  402. tixComboBox:GoState 12 $w
  403. }
  404. {3} {
  405. # data(ignore) was already set in state 3
  406. tixComboBox:GoState 4 $w
  407. }
  408. {5} {
  409. tixComboBox:GoState 7 $w
  410. }
  411. default {
  412. tixComboBox:StateError $w
  413. }
  414. }
  415. }
  416. proc tixComboBox:WidUp {w} {
  417. upvar #0 $w data
  418. switch -exact -- $data(state) {
  419. {1} {
  420. tixComboBox:GoState 12 $w
  421. }
  422. {5} {
  423. tixComboBox:GoState 13 $w
  424. }
  425. }
  426. }
  427. proc tixComboBox:LbBrowse {w args} {
  428. upvar #0 $w data
  429. set event [tixEvent type]
  430. set x [tixEvent flag x]
  431. set y [tixEvent flag y]
  432. set X [tixEvent flag X]
  433. set Y [tixEvent flag Y]
  434. if {$data(-state) eq "disabled"} { return }
  435. switch -exact -- $event {
  436. <1> {
  437. case $data(state) {
  438. {2} {
  439. tixComboBox:GoState 5 $w $x $y $X $Y
  440. }
  441. {5} {
  442. tixComboBox:GoState 5 $w $x $y $X $Y
  443. }
  444. {n0} {
  445. tixComboBox:GoState n6 $w $x $y $X $Y
  446. }
  447. default {
  448. tixComboBox:StateError $w
  449. }
  450. }
  451. }
  452. <ButtonRelease-1> {
  453. case $data(state) {
  454. {5} {
  455. tixComboBox:GoState 6 $w $x $y $X $Y
  456. }
  457. {n6} {
  458. tixComboBox:GoState n0 $w
  459. }
  460. default {
  461. tixComboBox:StateError $w
  462. }
  463. }
  464. }
  465. default {
  466. # Must be a motion event
  467. case $data(state) {
  468. {1} {
  469. tixComboBox:GoState 9 $w $x $y $X $Y
  470. }
  471. {5} {
  472. tixComboBox:GoState 5 $w $x $y $X $Y
  473. }
  474. {n6} {
  475. tixComboBox:GoState n6 $w $x $y $X $Y
  476. }
  477. default {
  478. tixComboBox:StateError $w
  479. }
  480. }
  481. }
  482. }
  483. }
  484. proc tixComboBox:LbCommand {w} {
  485. upvar #0 $w data
  486. if {$data(state) eq "n0"} {
  487. tixComboBox:GoState n1 $w
  488. }
  489. }
  490. #----------------------------------------------------------------------
  491. # General keyboard event
  492. # returns 1 if the combobox is in some special state and the Escape key
  493. # shouldn't be handled by the toplevel bind tag. As a result, when a combobox
  494. # is popped up in a dialog box, Escape will popdown the combo. If the combo
  495. # is not popped up, Escape will invoke the toplevel bindtag (which can
  496. # pop down the dialog box)
  497. #
  498. proc tixComboBox:EscKey {w} {
  499. upvar #0 $w data
  500. if {$data(-state) eq "disabled"} { return 0 }
  501. switch -exact -- $data(state) {
  502. {0} {
  503. tixComboBox:GoState 17 $w
  504. }
  505. {2} {
  506. tixComboBox:GoState 16 $w
  507. return 1
  508. }
  509. {n0} {
  510. tixComboBox:GoState n4 $w
  511. }
  512. default {
  513. # ignore
  514. return 1
  515. }
  516. }
  517. return 0
  518. }
  519. #----------------------------------------
  520. # Keyboard events
  521. #----------------------------------------
  522. proc tixComboBox:EntDirKey {w dir} {
  523. upvar #0 $w data
  524. if {$data(-state) eq "disabled"} { return }
  525. switch -exact -- $data(state) {
  526. {0} {
  527. tixComboBox:GoState 10 $w $dir
  528. }
  529. {2} {
  530. tixComboBox:GoState 11 $w $dir
  531. }
  532. {5} {
  533. # ignore
  534. }
  535. {n0} {
  536. tixComboBox:GoState n3 $w $dir
  537. }
  538. }
  539. }
  540. proc tixComboBox:EntReturnKey {w} {
  541. upvar #0 $w data
  542. if {$data(-state) eq "disabled"} { return }
  543. switch -exact -- $data(state) {
  544. {0} {
  545. tixComboBox:GoState 14 $w
  546. }
  547. {2} {
  548. tixComboBox:GoState 15 $w
  549. }
  550. {5} {
  551. # ignore
  552. }
  553. {n0} {
  554. tixComboBox:GoState n1 $w
  555. }
  556. }
  557. }
  558. # Return 1 == break from the binding == no keyboard focus traversal
  559. proc tixComboBox:EntTab {w} {
  560. upvar #0 $w data
  561. switch -exact -- $data(state) {
  562. {0} {
  563. tixComboBox:GoState 14 $w
  564. set data(cancelTab) ""
  565. return 0
  566. }
  567. {2} {
  568. tixComboBox:GoState 15 $w
  569. set data(cancelTab) ""
  570. return 0
  571. }
  572. {n0} {
  573. tixComboBox:GoState n1 $w
  574. set data(cancelTab) ""
  575. return 0
  576. }
  577. default {
  578. return 1
  579. }
  580. }
  581. }
  582. proc tixComboBox:EntKeyPress {w} {
  583. upvar #0 $w data
  584. if {$data(-state) eq "disabled" || !$data(-editable)} { return }
  585. switch -exact -- $data(state) {
  586. 0 - 2 - n0 {
  587. tixComboBox:ClearListboxSelection $w
  588. tixComboBox:SetSelection $w [$data(w:entry) get] 0 0
  589. }
  590. }
  591. }
  592. #----------------------------------------------------------------------
  593. proc tixComboBox:HandleDirKey {w dir} {
  594. upvar #0 $w data
  595. if {[tixComboBox:CheckListboxSelection $w]} {
  596. switch -exact -- $dir {
  597. "up" {
  598. tkListboxUpDown $data(w:listbox) -1
  599. set data(curIndex) [lindex [$data(w:listbox) curselection] 0]
  600. tixComboBox:SetSelectionFromListbox $w
  601. }
  602. "down" {
  603. tkListboxUpDown $data(w:listbox) 1
  604. set data(curIndex) [lindex [$data(w:listbox) curselection] 0]
  605. tixComboBox:SetSelectionFromListbox $w
  606. }
  607. "pageup" {
  608. $data(w:listbox) yview scroll -1 pages
  609. }
  610. "pagedown" {
  611. $data(w:listbox) yview scroll 1 pages
  612. }
  613. }
  614. } else {
  615. # There wasn't good selection in the listbox.
  616. #
  617. tixComboBox:SetSelectionFromListbox $w
  618. }
  619. }
  620. proc tixComboBox:Invoke {w} {
  621. upvar #0 $w data
  622. tixComboBox:SetValue $w $data(-selection)
  623. if {![winfo exists $w]} {
  624. return
  625. }
  626. if {$data(-history)} {
  627. tixComboBox:addhistory $w $data(-value)
  628. set data(curIndex) 0
  629. }
  630. $data(w:entry) selection from 0
  631. $data(w:entry) selection to end
  632. $data(w:entry) icursor end
  633. }
  634. #----------------------------------------------------------------------
  635. # MAINTAINING THE -VALUE
  636. #----------------------------------------------------------------------
  637. proc tixComboBox:SetValue {w newValue {noUpdate 0} {updateEnt 1}} {
  638. upvar #0 $w data
  639. if {[llength $data(-validatecmd)]} {
  640. set data(-value) [tixEvalCmdBinding $w $data(-validatecmd) "" $newValue]
  641. } else {
  642. set data(-value) $newValue
  643. }
  644. if {! $noUpdate} {
  645. tixVariable:UpdateVariable $w
  646. }
  647. if {$updateEnt} {
  648. if {!$data(-editable)} {
  649. $data(w:entry) delete 0 end
  650. $data(w:entry) insert 0 $data(-value)
  651. }
  652. }
  653. if {!$data(-disablecallback) && [llength $data(-command)]} {
  654. if {![info exists data(varInited)]} {
  655. set bind(specs) {%V}
  656. set bind(%V) $data(-value)
  657. tixEvalCmdBinding $w $data(-command) bind $data(-value)
  658. if {![winfo exists $w]} {
  659. # The user destroyed the window!
  660. return
  661. }
  662. }
  663. }
  664. set data(-selection) $data(-value)
  665. if {$updateEnt} {
  666. tixSetEntry $data(w:entry) $data(-value)
  667. if {$data(-anchor) eq "e"} {
  668. tixComboBox:EntryAlignEnd $w
  669. }
  670. }
  671. }
  672. # markSel: should the all the text in the entry be highlighted?
  673. #
  674. proc tixComboBox:SetSelection {w value {markSel 1} {setent 1}} {
  675. upvar #0 $w data
  676. if {$setent} {
  677. tixSetEntry $data(w:entry) $value
  678. }
  679. set data(-selection) $value
  680. if {$data(-selectmode) eq "browse"} {
  681. if {$markSel} {
  682. $data(w:entry) selection range 0 end
  683. }
  684. if {[llength $data(-browsecmd)]} {
  685. set bind(specs) {%V}
  686. set bind(%V) [$data(w:entry) get]
  687. tixEvalCmdBinding $w $data(-browsecmd) bind [$data(w:entry) get]
  688. }
  689. } else {
  690. tixComboBox:SetValue $w $value 0 0
  691. }
  692. }
  693. proc tixComboBox:ClearListboxSelection {w} {
  694. upvar #0 $w data
  695. if {![winfo exists $data(w:listbox)]} {
  696. tixDebug "tixComboBox:ClearListboxSelection error non-existent $data(w:listbox)"
  697. return
  698. }
  699. $data(w:listbox) selection clear 0 end
  700. }
  701. proc tixComboBox:UpdateListboxSelection {w index} {
  702. upvar #0 $w data
  703. if {![winfo exists $data(w:listbox)]} {
  704. tixDebug "tixComboBox:UpdateListboxSelection error non-existent $data(w:listbox)"
  705. return
  706. }
  707. if {$index != ""} {
  708. $data(w:listbox) selection set $index
  709. $data(w:listbox) selection anchor $index
  710. }
  711. }
  712. proc tixComboBox:Cancel {w} {
  713. upvar #0 $w data
  714. tixSetEntry $data(w:entry) $data(-value)
  715. tixComboBox:SetSelection $w $data(-value)
  716. if {[tixComboBox:LbGetSelection $w] ne $data(-selection)} {
  717. tixComboBox:ClearListboxSelection $w
  718. }
  719. }
  720. proc tixComboBox:flash {w} {
  721. tixComboBox:BlinkEntry $w
  722. }
  723. # Make the entry blink when the user selects a choice
  724. #
  725. proc tixComboBox:BlinkEntry {w} {
  726. upvar #0 $w data
  727. if {![info exists data(entryBlacken)]} {
  728. set old_bg [$data(w:entry) cget -bg]
  729. set old_fg [$data(w:entry) cget -fg]
  730. $data(w:entry) config -fg $old_bg
  731. $data(w:entry) config -bg $old_fg
  732. set data(entryBlacken) 1
  733. after 50 tixComboBox:RestoreBlink $w [list $old_bg] [list $old_fg]
  734. }
  735. }
  736. proc tixComboBox:RestoreBlink {w old_bg old_fg} {
  737. upvar #0 $w data
  738. if {[info exists data(w:entry)] && [winfo exists $data(w:entry)]} {
  739. $data(w:entry) config -fg $old_fg
  740. $data(w:entry) config -bg $old_bg
  741. }
  742. if {[info exists data(entryBlacken)]} {
  743. unset data(entryBlacken)
  744. }
  745. }
  746. #----------------------------------------
  747. # Handle events inside the list box
  748. #----------------------------------------
  749. proc tixComboBox:LbIndex {w {flag ""}} {
  750. upvar #0 $w data
  751. if {![winfo exists $data(w:listbox)]} {
  752. tixDebug "tixComboBox:LbIndex error non-existent $data(w:listbox)"
  753. if {$flag eq "emptyOK"} {
  754. return ""
  755. } else {
  756. return 0
  757. }
  758. }
  759. set sel [lindex [$data(w:listbox) curselection] 0]
  760. if {$sel != ""} {
  761. return $sel
  762. } else {
  763. if {$flag eq "emptyOK"} {
  764. return ""
  765. } else {
  766. return 0
  767. }
  768. }
  769. }
  770. #----------------------------------------------------------------------
  771. #
  772. # STATE MANIPULATION
  773. #
  774. #----------------------------------------------------------------------
  775. proc tixComboBox:GoState-0 {w} {
  776. upvar #0 $w data
  777. if {[info exists data(w:root)] && [grab current] eq "$data(w:root)"} {
  778. grab release $w
  779. }
  780. }
  781. proc tixComboBox:GoState-1 {w} {
  782. upvar #0 $w data
  783. tixComboBox:Popup $w
  784. }
  785. proc tixComboBox:GoState-2 {w} {
  786. upvar #0 $w data
  787. }
  788. proc tixComboBox:GoState-3 {w} {
  789. upvar #0 $w data
  790. set data(ignore) 1
  791. tixComboBox:Popdown $w
  792. }
  793. proc tixComboBox:GoState-4 {w} {
  794. upvar #0 $w data
  795. tixComboBox:Ungrab $w
  796. if {$data(ignore)} {
  797. tixComboBox:Cancel $w
  798. } else {
  799. tixComboBox:Invoke $w
  800. }
  801. tixComboBox:GoState 0 $w
  802. }
  803. proc tixComboBox:GoState-5 {w x y X Y} {
  804. upvar #0 $w data
  805. tixComboBox:LbSelect $w $x $y $X $Y
  806. }
  807. proc tixComboBox:GoState-6 {w x y X Y} {
  808. upvar #0 $w data
  809. tixComboBox:Popdown $w
  810. if {[tixWithinWindow $data(w:shell) $X $Y]} {
  811. set data(ignore) 0
  812. } else {
  813. set data(ignore) 1
  814. }
  815. tixComboBox:GoState 4 $w
  816. }
  817. proc tixComboBox:GoState-7 {w} {
  818. upvar #0 $w data
  819. tixComboBox:Popdown $w
  820. set data(ignore) 1
  821. catch {
  822. global tkPriv
  823. if {$tkPriv(afterId) != ""} {
  824. tkCancelRepeat
  825. }
  826. }
  827. set data(ignore) 1
  828. tixComboBox:GoState 4 $w
  829. }
  830. proc tixComboBox:GoState-9 {w x y X Y} {
  831. upvar #0 $w data
  832. catch {
  833. tkButtonUp $data(w:arrow)
  834. }
  835. tixComboBox:GoState 5 $w $x $y $X $Y
  836. }
  837. proc tixComboBox:GoState-10 {w dir} {
  838. upvar #0 $w data
  839. tixComboBox:Popup $w
  840. if {![tixComboBox:CheckListboxSelection $w]} {
  841. # There wasn't good selection in the listbox.
  842. #
  843. tixComboBox:SetSelectionFromListbox $w
  844. }
  845. tixComboBox:GoState 2 $w
  846. }
  847. proc tixComboBox:GoState-11 {w dir} {
  848. upvar #0 $w data
  849. tixComboBox:HandleDirKey $w $dir
  850. tixComboBox:GoState 2 $w
  851. }
  852. proc tixComboBox:GoState-12 {w} {
  853. upvar #0 $w data
  854. catch {
  855. tkButtonUp $data(w:arrow)
  856. }
  857. tixComboBox:GoState 2 $w
  858. }
  859. proc tixComboBox:GoState-13 {w} {
  860. upvar #0 $w data
  861. catch {
  862. global tkPriv
  863. if {$tkPriv(afterId) != ""} {
  864. tkCancelRepeat
  865. }
  866. }
  867. tixComboBox:GoState 2 $w
  868. }
  869. proc tixComboBox:GoState-14 {w} {
  870. upvar #0 $w data
  871. tixComboBox:Invoke $w
  872. tixComboBox:GoState 0 $w
  873. }
  874. proc tixComboBox:GoState-15 {w} {
  875. upvar #0 $w data
  876. tixComboBox:Popdown $w
  877. set data(ignore) 0
  878. tixComboBox:GoState 4 $w
  879. }
  880. proc tixComboBox:GoState-16 {w} {
  881. upvar #0 $w data
  882. tixComboBox:Popdown $w
  883. tixComboBox:Cancel $w
  884. set data(ignore) 1
  885. tixComboBox:GoState 4 $w
  886. }
  887. proc tixComboBox:GoState-17 {w} {
  888. upvar #0 $w data
  889. tixComboBox:Cancel $w
  890. tixComboBox:GoState 0 $w
  891. }
  892. proc tixComboBox:GoState-19 {w} {
  893. upvar #0 $w data
  894. set data(ignore) [string equal $data(-selection) $data(-value)]
  895. tixComboBox:Popdown $w
  896. }
  897. #----------------------------------------------------------------------
  898. # Non-dropdown states
  899. #----------------------------------------------------------------------
  900. proc tixComboBox:GoState-n0 {w} {
  901. upvar #0 $w data
  902. }
  903. proc tixComboBox:GoState-n1 {w} {
  904. upvar #0 $w data
  905. tixComboBox:Invoke $w
  906. tixComboBox:GoState n0 $w
  907. }
  908. proc tixComboBox:GoState-n3 {w dir} {
  909. upvar #0 $w data
  910. tixComboBox:HandleDirKey $w $dir
  911. tixComboBox:GoState n0 $w
  912. }
  913. proc tixComboBox:GoState-n4 {w} {
  914. upvar #0 $w data
  915. tixComboBox:Cancel $w
  916. tixComboBox:GoState n0 $w
  917. }
  918. proc tixComboBox:GoState-n6 {w x y X Y} {
  919. upvar #0 $w data
  920. tixComboBox:LbSelect $w $x $y $X $Y
  921. }
  922. #----------------------------------------------------------------------
  923. # General State Manipulation
  924. #----------------------------------------------------------------------
  925. proc tixComboBox:GoState {s w args} {
  926. upvar #0 $w data
  927. tixComboBox:SetState $w $s
  928. eval tixComboBox:GoState-$s $w $args
  929. }
  930. proc tixComboBox:SetState {w s} {
  931. upvar #0 $w data
  932. # catch {puts [info level -2]}
  933. # puts "setting state $data(state) --> $s"
  934. set data(state) $s
  935. }
  936. proc tixComboBox:StateError {w} {
  937. upvar #0 $w data
  938. # error "wrong state $data(state)"
  939. }
  940. #----------------------------------------------------------------------
  941. # Listbox handling
  942. #----------------------------------------------------------------------
  943. # Set a selection if there isn't one. Returns true if there was already
  944. # a good selection inside the listbox
  945. #
  946. proc tixComboBox:CheckListboxSelection {w} {
  947. upvar #0 $w data
  948. if {![winfo exists $data(w:listbox)]} {
  949. tixDebug "tixComboBox:CheckListboxSelection error non-existent $data(w:listbox)"
  950. return 0
  951. }
  952. if {[$data(w:listbox) curselection] == ""} {
  953. if {$data(curIndex) == ""} {
  954. set data(curIndex) 0
  955. }
  956. $data(w:listbox) activate $data(curIndex)
  957. $data(w:listbox) selection clear 0 end
  958. $data(w:listbox) selection set $data(curIndex)
  959. $data(w:listbox) see $data(curIndex)
  960. return 0
  961. } else {
  962. return 1
  963. }
  964. }
  965. proc tixComboBox:SetSelectionFromListbox {w} {
  966. upvar #0 $w data
  967. set string [$data(w:listbox) get $data(curIndex)]
  968. tixComboBox:SetSelection $w $string
  969. tixComboBox:UpdateListboxSelection $w $data(curIndex)
  970. }
  971. proc tixComboBox:LbGetSelection {w} {
  972. upvar #0 $w data
  973. set index [tixComboBox:LbIndex $w emptyOK]
  974. if {$index >=0} {
  975. return [$data(w:listbox) get $index]
  976. } else {
  977. return ""
  978. }
  979. }
  980. proc tixComboBox:LbSelect {w x y X Y} {
  981. upvar #0 $w data
  982. set index [tixComboBox:LbIndex $w emptyOK]
  983. if {$index == ""} {
  984. set index [$data(w:listbox) nearest $y]
  985. }
  986. if {$index >= 0} {
  987. if {[focus -lastfor $data(w:entry)] ne $data(w:entry) &&
  988. [focus -lastfor $data(w:entry)] ne $data(w:listbox)} {
  989. focus $data(w:entry)
  990. }
  991. set string [$data(w:listbox) get $index]
  992. tixComboBox:SetSelection $w $string
  993. tixComboBox:UpdateListboxSelection $w $index
  994. }
  995. }
  996. #----------------------------------------------------------------------
  997. # Internal commands
  998. #----------------------------------------------------------------------
  999. proc tixComboBox:CrossBtn {w} {
  1000. upvar #0 $w data
  1001. $data(w:entry) delete 0 end
  1002. tixComboBox:ClearListboxSelection $w
  1003. tixComboBox:SetSelection $w ""
  1004. }
  1005. #--------------------------------------------------
  1006. # Popping up list shell
  1007. #--------------------------------------------------
  1008. # Popup the listbox and grab
  1009. #
  1010. #
  1011. proc tixComboBox:Popup {w} {
  1012. global tcl_platform
  1013. upvar #0 $w data
  1014. if {![winfo ismapped $data(w:root)]} {
  1015. return
  1016. }
  1017. #---------------------------------------------------------------------
  1018. # Pop up
  1019. #
  1020. if {$data(-listcmd) != ""} {
  1021. # This option allows the user to fill in the listbox on demand
  1022. #
  1023. tixEvalCmdBinding $w $data(-listcmd)
  1024. }
  1025. # calculate the size
  1026. set y [winfo rooty $data(w:entry)]
  1027. incr y [winfo height $data(w:entry)]
  1028. incr y 3
  1029. set bd [$data(w:shell) cget -bd]
  1030. # incr bd [$data(w:shell) cget -highlightthickness]
  1031. set height [expr {[winfo reqheight $data(w:slistbox)] + 2*$bd}]
  1032. set x1 [winfo rootx $data(w:entry)]
  1033. if {$data(-listwidth) == ""} {
  1034. if {[winfo ismapped $data(w:arrow)]} {
  1035. set x2 [winfo rootx $data(w:arrow)]
  1036. if {$x2 >= $x1} {
  1037. incr x2 [winfo width $data(w:arrow)]
  1038. set width [expr {$x2 - $x1}]
  1039. } else {
  1040. set width [winfo width $data(w:entry)]
  1041. set x2 [expr {$x1 + $width}]
  1042. }
  1043. } else {
  1044. set width [winfo width $data(w:entry)]
  1045. set x2 [expr {$x1 + $width}]
  1046. }
  1047. } else {
  1048. set width $data(-listwidth)
  1049. set x2 [expr {$x1 + $width}]
  1050. }
  1051. set reqwidth [winfo reqwidth $data(w:shell)]
  1052. if {$reqwidth < $width} {
  1053. set reqwidth $width
  1054. } else {
  1055. if {$reqwidth > [expr {$width *3}]} {
  1056. set reqwidth [expr {$width *3}]
  1057. }
  1058. if {$reqwidth > [winfo vrootwidth .]} {
  1059. set reqwidth [winfo vrootwidth .]
  1060. }
  1061. }
  1062. set width $reqwidth
  1063. # If the listbox is too far right, pull it back to the left
  1064. #
  1065. set scrwidth [winfo vrootwidth .]
  1066. if {$x2 > $scrwidth} {
  1067. set x1 [expr {$scrwidth - $width}]
  1068. }
  1069. # If the listbox is too far left, pull it back to the right
  1070. #
  1071. if {$x1 < 0} {
  1072. set x1 0
  1073. }
  1074. # If the listbox is below bottom of screen, put it upwards
  1075. #
  1076. set scrheight [winfo vrootheight .]
  1077. set bottom [expr {$y+$height}]
  1078. if {$bottom > $scrheight} {
  1079. set y [expr {$y-$height-[winfo height $data(w:entry)]-5}]
  1080. }
  1081. # OK , popup the shell
  1082. #
  1083. global tcl_platform
  1084. wm geometry $data(w:shell) $reqwidth\x$height+$x1+$y
  1085. if {$tcl_platform(platform) eq "windows"} {
  1086. update
  1087. }
  1088. wm deiconify $data(w:shell)
  1089. if {$tcl_platform(platform) eq "windows"} {
  1090. update
  1091. }
  1092. raise $data(w:shell)
  1093. focus $data(w:entry)
  1094. set data(popped) 1
  1095. # add for safety
  1096. update
  1097. tixComboBox:Grab $w
  1098. }
  1099. proc tixComboBox:SetCursor {w cursor} {
  1100. upvar #0 $w data
  1101. $w config -cursor $cursor
  1102. }
  1103. proc tixComboBox:Popdown {w} {
  1104. upvar #0 $w data
  1105. wm withdraw $data(w:shell)
  1106. tixComboBox:SetCursor $w ""
  1107. }
  1108. # Grab the server so that user cannot move the windows around
  1109. proc tixComboBox:Grab {w} {
  1110. upvar #0 $w data
  1111. tixComboBox:SetCursor $w arrow
  1112. if {[catch {
  1113. # We catch here because grab may fail under a lot of circumstances
  1114. # Just don't want to break the code ...
  1115. switch -exact -- $data(-grab) {
  1116. global { tixPushGrab -global $data(w:root) }
  1117. local { tixPushGrab $data(w:root) }
  1118. }
  1119. } err]} {
  1120. tixDebug "tixComboBox:Grab+: Error grabbing $data(w:root)\n$err"
  1121. }
  1122. }
  1123. proc tixComboBox:Ungrab {w} {
  1124. upvar #0 $w data
  1125. if {[catch {
  1126. catch {
  1127. switch -exact -- $data(-grab) {
  1128. global { tixPopGrab }
  1129. local { tixPopGrab }
  1130. }
  1131. }
  1132. } err]} {
  1133. tixDebug "tixComboBox:Grab+: Error grabbing $data(w:root)\n$err"
  1134. }
  1135. }
  1136. #----------------------------------------------------------------------
  1137. # Alignment
  1138. #----------------------------------------------------------------------
  1139. # The following two routines can emulate a "right align mode" for the
  1140. # entry in the combo box.
  1141. proc tixComboBox:EntryAlignEnd {w} {
  1142. upvar #0 $w data
  1143. $data(w:entry) xview end
  1144. }
  1145. proc tixComboBox:Destructor {w} {
  1146. upvar #0 $w data
  1147. tixUnsetMegaWidget $data(w:entry)
  1148. tixVariable:DeleteVariable $w
  1149. # Chain this to the superclass
  1150. #
  1151. tixChainMethod $w Destructor
  1152. }
  1153. #----------------------------------------------------------------------
  1154. # CONFIG OPTIONS
  1155. #----------------------------------------------------------------------
  1156. proc tixComboBox:config-state {w value} {
  1157. upvar #0 $w data
  1158. catch {if {[$data(w:arrow) cget -state] eq $value} {set a 1}}
  1159. if {[info exists a]} {
  1160. return
  1161. }
  1162. catch {$data(w:arrow) config -state $value}
  1163. catch {$data(w:tick) config -state $value}
  1164. catch {$data(w:cross) config -state $value}
  1165. catch {$data(w:slistbox) config -state $value}
  1166. if {[string equal $value normal]} {
  1167. set fg [$data(w:arrow) cget -fg]
  1168. set entryFg $data(entryfg)
  1169. set lbSelFg [lindex [$data(w:listbox) config -selectforeground] 3]
  1170. set lbSelBg [lindex [$data(w:listbox) config -selectbackground] 3]
  1171. set entrySelFg [lindex [$data(w:entry) config -selectforeground] 3]
  1172. set entrySelBg [lindex [$data(w:entry) config -selectbackground] 3]
  1173. } else {
  1174. set fg [$data(w:arrow) cget -disabledforeground]
  1175. set entryFg $data(-disabledforeground)
  1176. set lbSelFg $entryFg
  1177. set lbSelBg [$data(w:listbox) cget -bg]
  1178. set entrySelFg $entryFg
  1179. set entrySelBg [$data(w:entry) cget -bg]
  1180. }
  1181. if {$fg ne ""} {
  1182. $data(w:label) config -fg $fg
  1183. $data(w:listbox) config -fg $fg -selectforeground $lbSelFg \
  1184. -selectbackground $lbSelBg
  1185. }
  1186. $data(w:entry) config -fg $entryFg -selectforeground $entrySelFg \
  1187. -selectbackground $entrySelBg
  1188. if {$value eq "normal"} {
  1189. if {$data(-editable)} {
  1190. $data(w:entry) config -state normal
  1191. }
  1192. $data(w:entry) config -takefocus 1
  1193. } else {
  1194. if {$data(-editable)} {
  1195. $data(w:entry) config -state disabled
  1196. }
  1197. $data(w:entry) config -takefocus 0
  1198. }
  1199. }
  1200. proc tixComboBox:config-value {w value} {
  1201. upvar #0 $w data
  1202. tixComboBox:SetValue $w $value
  1203. set data(-selection) $value
  1204. if {[tixComboBox:LbGetSelection $w] ne $value} {
  1205. tixComboBox:ClearListboxSelection $w
  1206. }
  1207. }
  1208. proc tixComboBox:config-selection {w value} {
  1209. upvar #0 $w data
  1210. tixComboBox:SetSelection $w $value
  1211. if {[tixComboBox:LbGetSelection $w] ne $value} {
  1212. tixComboBox:ClearListboxSelection $w
  1213. }
  1214. }
  1215. proc tixComboBox:config-variable {w arg} {
  1216. upvar #0 $w data
  1217. if {[tixVariable:ConfigVariable $w $arg]} {
  1218. # The value of data(-value) is changed if tixVariable:ConfigVariable
  1219. # returns true
  1220. set data(-selection) $data(-value)
  1221. tixComboBox:SetValue $w $data(-value) 1
  1222. }
  1223. catch {
  1224. unset data(varInited)
  1225. }
  1226. set data(-variable) $arg
  1227. }
  1228. #----------------------------------------------------------------------
  1229. # WIDGET COMMANDS
  1230. #----------------------------------------------------------------------
  1231. proc tixComboBox:align {w args} {
  1232. upvar #0 $w data
  1233. if {$data(-anchor) eq "e"} {
  1234. tixComboBox:EntryAlignEnd $w
  1235. }
  1236. }
  1237. proc tixComboBox:addhistory {w value} {
  1238. upvar #0 $w data
  1239. tixComboBox:insert $w 0 $value
  1240. $data(w:listbox) selection clear 0 end
  1241. if {$data(-prunehistory)} {
  1242. # Prune from the end
  1243. #
  1244. set max [$data(w:listbox) size]
  1245. if {$max <= 1} {
  1246. return
  1247. }
  1248. for {set i [expr {$max -1}]} {$i >= 1} {incr i -1} {
  1249. if {[$data(w:listbox) get $i] eq $value} {
  1250. $data(w:listbox) delete $i
  1251. break
  1252. }
  1253. }
  1254. }
  1255. }
  1256. proc tixComboBox:appendhistory {w value} {
  1257. upvar #0 $w data
  1258. tixComboBox:insert $w end $value
  1259. $data(w:listbox) selection clear 0 end
  1260. if {$data(-prunehistory)} {
  1261. # Prune from the end
  1262. #
  1263. set max [$data(w:listbox) size]
  1264. if {$max <= 1} {
  1265. return
  1266. }
  1267. for {set i [expr {$max -2}]} {$i >= 0} {incr i -1} {
  1268. if {[$data(w:listbox) get $i] eq $value} {
  1269. $data(w:listbox) delete $i
  1270. break
  1271. }
  1272. }
  1273. }
  1274. }
  1275. proc tixComboBox:insert {w index newitem} {
  1276. upvar #0 $w data
  1277. $data(w:listbox) insert $index $newitem
  1278. if {$data(-history) && $data(-historylimit) != ""
  1279. && [$data(w:listbox) size] eq $data(-historylimit)} {
  1280. $data(w:listbox) delete 0
  1281. }
  1282. }
  1283. proc tixComboBox:pick {w index} {
  1284. upvar #0 $w data
  1285. $data(w:listbox) activate $index
  1286. $data(w:listbox) selection clear 0 end
  1287. $data(w:listbox) selection set active
  1288. $data(w:listbox) see active
  1289. set text [$data(w:listbox) get $index]
  1290. tixComboBox:SetValue $w $text
  1291. set data(curIndex) $index
  1292. }
  1293. proc tixComboBox:invoke {w} {
  1294. tixComboBox:Invoke $w
  1295. }
  1296. proc tixComboBox:popdown {w} {
  1297. upvar #0 $w data
  1298. if {$data(-dropdown)} {
  1299. tixComboBox:Popdown $w
  1300. }
  1301. }