home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Freeware 31 / FreelogHS31.iso / Texte / scribus / scribus-1.3.3.9-win32-install.exe / tcl / tix8.1 / ComboBox.tcl < prev    next >
Text File  |  2002-01-24  |  38KB  |  1,607 lines

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