home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / optionmenu.itk < prev    next >
Text File  |  2003-09-01  |  22KB  |  665 lines

  1. #
  2. # Optionmenu
  3. # ----------------------------------------------------------------------
  4. # Implements an option menu widget with options to manage it. 
  5. # An option menu displays a frame containing a label and a button.
  6. # A pop-up menu will allow for the value of the button to change. 
  7. #
  8. # ----------------------------------------------------------------------
  9. #  AUTHOR:  Alfredo Jahn             Phone: (214) 519-3545
  10. #                                    Email: ajahn@spd.dsccc.com
  11. #                                           alfredo@wn.com
  12. #
  13. #  @(#) $Id: optionmenu.itk,v 1.9 2001/10/26 15:28:22 smithc Exp $
  14. # ----------------------------------------------------------------------
  15. #            Copyright (c) 1995 DSC Technologies Corporation
  16. # ======================================================================
  17. # Permission to use, copy, modify, distribute and license this software 
  18. # and its documentation for any purpose, and without fee or written 
  19. # agreement with DSC, is hereby granted, provided that the above copyright 
  20. # notice appears in all copies and that both the copyright notice and 
  21. # warranty disclaimer below appear in supporting documentation, and that 
  22. # the names of DSC Technologies Corporation or DSC Communications 
  23. # Corporation not be used in advertising or publicity pertaining to the 
  24. # software without specific, written prior permission.
  25. # DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
  26. # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
  27. # INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
  28. # AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, 
  29. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL 
  30. # DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
  31. # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
  32. # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
  33. # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
  34. # SOFTWARE.
  35. # ======================================================================
  36.  
  37. #
  38. # Default resources.
  39. #
  40.  
  41. option add *Optionmenu.highlightThickness    1    widgetDefault
  42. option add *Optionmenu.borderWidth        2    widgetDefault
  43. option add *Optionmenu.labelPos            w    widgetDefault
  44. option add *Optionmenu.labelMargin        2    widgetDefault
  45. option add *Optionmenu.popupCursor        arrow    widgetDefault
  46.  
  47. #
  48. # Usual options.
  49. #
  50. itk::usual Optionmenu {
  51.     keep -activebackground -activeborderwidth -activeforeground \
  52.      -background -borderwidth -cursor -disabledforeground -font \
  53.      -foreground -highlightcolor -highlightthickness -labelfont \
  54.      -popupcursor
  55. }
  56.  
  57. # ------------------------------------------------------------------
  58. #                            OPTONMENU
  59. # ------------------------------------------------------------------
  60. itcl::class iwidgets::Optionmenu {
  61.     inherit iwidgets::Labeledwidget
  62.     
  63.     constructor {args} {}
  64.     destructor {}
  65.  
  66.     itk_option define -clicktime clickTime ClickTime 150
  67.     itk_option define -command command Command {}
  68.     itk_option define -cyclicon cyclicOn CyclicOn true
  69.     itk_option define -width width Width 0
  70.     itk_option define -font font Font -Adobe-Helvetica-Bold-R-Normal--*-120-*
  71.     itk_option define -borderwidth borderWidth BorderWidth 2
  72.     itk_option define -highlightthickness highlightThickness HighlightThickness 1
  73.     itk_option define -state state State normal
  74.  
  75.     public {
  76.       method index {index} 
  77.       method delete {first {last {}}} 
  78.       method disable {index} 
  79.       method enable {args} 
  80.       method get {{first "current"} {last ""}} 
  81.       method insert {index string args} 
  82.       method popupMenu {args} 
  83.       method select {index} 
  84.       method sort {{mode "increasing"}} 
  85.     }
  86.  
  87.     protected {
  88.       variable _calcSize ""  ;# non-null => _calcSize pending
  89.     }
  90.  
  91.     private {
  92.       method _buttonRelease {time} 
  93.       method _getNextItem {index} 
  94.       method _next {} 
  95.       method _postMenu {time} 
  96.       method _previous {} 
  97.       method _setItem {item} 
  98.       method _setSize {{when later}} 
  99.       method _setitems {items} ;# Set the list of menu entries
  100.  
  101.       variable _postTime 0
  102.       variable _items {}       ;# List of popup menu entries
  103.       variable _numitems 0     ;# List of popup menu entries
  104.  
  105.       variable _currentItem "" ;# Active menu selection
  106.     }
  107. }
  108.  
  109. #
  110. # Provide a lowercased access method for the Optionmenu class.
  111. proc ::iwidgets::optionmenu {pathName args} {
  112.     uplevel ::iwidgets::Optionmenu $pathName $args
  113. }
  114.  
  115. # ------------------------------------------------------------------
  116. #                        CONSTRUCTOR
  117. # ------------------------------------------------------------------
  118. itcl::body iwidgets::Optionmenu::constructor {args} {
  119.     global tcl_platform
  120.  
  121.     component hull configure -highlightthickness 0
  122.  
  123.     itk_component add menuBtn {
  124.     menubutton $itk_interior.menuBtn -relief raised -indicatoron on \
  125.             -textvariable [itcl::scope _currentItem] -takefocus 1 \
  126.             -menu $itk_interior.menuBtn.menu
  127.     } {
  128.         usual
  129.     keep -borderwidth
  130.         if {$tcl_platform(platform) != "unix"} {
  131.             ignore -activebackground -activeforeground
  132.         }
  133.     }
  134.     pack $itk_interior.menuBtn -fill x
  135.     pack propagate $itk_interior no
  136.  
  137.     itk_component add popupMenu {
  138.     menu $itk_interior.menuBtn.menu -tearoff no
  139.     } {
  140.     usual
  141.     ignore -tearoff
  142.     keep -activeborderwidth -borderwidth
  143.     rename -cursor -popupcursor popupCursor Cursor
  144.     }
  145.  
  146.     #
  147.     # Bind to button release for all components.
  148.     #
  149.     bind $itk_component(menuBtn) <ButtonPress-1> \
  150.         "[itcl::code $this _postMenu %t]; break"
  151.     bind $itk_component(menuBtn) <KeyPress-space> \
  152.         "[itcl::code $this _postMenu %t]; break"
  153.     bind $itk_component(popupMenu) <ButtonRelease-1> \
  154.         [itcl::code $this _buttonRelease %t]
  155.  
  156.     #
  157.     # Initialize the widget based on the command line options.
  158.     #
  159.     eval itk_initialize $args
  160. }
  161.  
  162. # ------------------------------------------------------------------
  163. #                           DESTRUCTOR
  164. # ------------------------------------------------------------------
  165. itcl::body iwidgets::Optionmenu::destructor {} {
  166.     if {$_calcSize != ""} {after cancel $_calcSize}
  167. }
  168.  
  169. # ------------------------------------------------------------------
  170. #                             OPTIONS
  171. # ------------------------------------------------------------------
  172.  
  173. # ------------------------------------------------------------------
  174. # OPTION -clicktime
  175. #
  176. # Interval time (in msec) used to determine that a single mouse 
  177. # click has occurred. Used to post menu on a quick mouse click.
  178. # **WARNING** changing this value may cause the sigle-click 
  179. # functionality to not work properly!
  180. # ------------------------------------------------------------------
  181. itcl::configbody iwidgets::Optionmenu::clicktime {}
  182.  
  183. # ------------------------------------------------------------------
  184. # OPTION -command
  185. #
  186. # Specifies a command to be evaluated upon change in option menu.
  187. # ------------------------------------------------------------------
  188. itcl::configbody iwidgets::Optionmenu::command {}
  189.  
  190. # ------------------------------------------------------------------
  191. # OPTION -cyclicon
  192. #
  193. # Turns on/off the 3rd mouse button capability. This feature
  194. # allows the right mouse button to cycle through the popup 
  195. # menu list without poping it up. <shift>M3 cycles through
  196. # the menu in reverse order.
  197. # ------------------------------------------------------------------
  198. itcl::configbody iwidgets::Optionmenu::cyclicon {
  199.     if {$itk_option(-cyclicon)} {
  200.         bind $itk_component(menuBtn) <3> [itcl::code $this _next]
  201.         bind $itk_component(menuBtn) <Shift-3> [itcl::code $this _previous]
  202.         bind $itk_component(menuBtn) <KeyPress-Down> [itcl::code $this _next]
  203.         bind $itk_component(menuBtn) <KeyPress-Up> [itcl::code $this _previous]
  204.     } else {
  205.         bind $itk_component(menuBtn) <3> break
  206.         bind $itk_component(menuBtn) <Shift-3> break
  207.         bind $itk_component(menuBtn) <KeyPress-Down> break
  208.         bind $itk_component(menuBtn) <KeyPress-Up> break
  209.     }
  210. }
  211.  
  212. # ------------------------------------------------------------------
  213. # OPTION -width
  214. #
  215. # Allows the menu label width to be set to a fixed size
  216. # ------------------------------------------------------------------
  217. itcl::configbody iwidgets::Optionmenu::width {
  218.     _setSize
  219. }
  220.  
  221. # ------------------------------------------------------------------
  222. # OPTION -font
  223. #
  224. # Change all fonts for this widget. Also re-calculate height based
  225. # on font size (used to line up menu items over menu button label).
  226. # ------------------------------------------------------------------
  227. itcl::configbody iwidgets::Optionmenu::font {
  228.     _setSize
  229. }
  230.  
  231. # ------------------------------------------------------------------
  232. # OPTION -borderwidth
  233. #
  234. # Change borderwidth for this widget. Also re-calculate height based
  235. # on font size (used to line up menu items over menu button label).
  236. # ------------------------------------------------------------------
  237. itcl::configbody iwidgets::Optionmenu::borderwidth {
  238.     _setSize
  239. }
  240.  
  241. # ------------------------------------------------------------------
  242. # OPTION -highlightthickness
  243. #
  244. # Change highlightthickness for this widget. Also re-calculate
  245. # height based on font size (used to line up menu items over
  246. # menu button label).
  247. # ------------------------------------------------------------------
  248. itcl::configbody iwidgets::Optionmenu::highlightthickness {
  249.     _setSize
  250. }
  251.  
  252. # ------------------------------------------------------------------
  253. # OPTION -state
  254. #
  255. # Specified one of two states for the Optionmenu: normal, or
  256. # disabled.  If the Optionmenu is disabled, then option menu
  257. # selection is ignored.
  258. # ------------------------------------------------------------------
  259. itcl::configbody iwidgets::Optionmenu::state {
  260.     switch $itk_option(-state) {
  261.         normal {
  262.             $itk_component(menuBtn) config -state normal
  263.             $itk_component(label) config -fg $itk_option(-foreground)
  264.         } 
  265.         disabled {
  266.             $itk_component(menuBtn) config -state disabled
  267.             $itk_component(label) config -fg $itk_option(-disabledforeground)
  268.         }
  269.         default {
  270.             error "bad state option \"$itk_option(-state)\":\
  271.             should be disabled or normal"
  272.         }
  273.     }
  274. }
  275.  
  276. # ------------------------------------------------------------------
  277. #                            METHODS
  278. # ------------------------------------------------------------------
  279.  
  280. # ------------------------------------------------------------------
  281. # METHOD: index index
  282. #
  283. # Return the numerical index corresponding to index.
  284. # ------------------------------------------------------------------
  285. itcl::body iwidgets::Optionmenu::index {index} {
  286.  
  287.     if {[regexp {(^[0-9]+$)} $index]} {
  288.     set idx [$itk_component(popupMenu) index $index]
  289.  
  290.     if {$idx == "none"} {
  291.         return 0
  292.     }
  293.     return [expr {$index > $idx ? $_numitems : $idx}]
  294.     
  295.     } elseif {$index == "end"} {
  296.     return [expr {$_numitems - 1}]
  297.     
  298.     } elseif {$index == "select"} {
  299.     return [lsearch $_items $_currentItem]
  300.     
  301.     }
  302.  
  303.     set numValue [lsearch -glob $_items $index]
  304.  
  305.     if {$numValue == -1} {
  306.         error "bad Optionmenu index \"$index\""
  307.     }
  308.     return $numValue
  309. }
  310.  
  311. # ------------------------------------------------------------------
  312. # METHOD: delete first ?last?
  313. #
  314. # Remove an item (or range of items) from the popup menu. 
  315. # ------------------------------------------------------------------
  316. itcl::body iwidgets::Optionmenu::delete {first {last {}}} {
  317.  
  318.     set first [index $first]
  319.     set last [expr {$last != {} ? [index $last] : $first}]    
  320.     set nextAvail $_currentItem
  321.     
  322.     #
  323.     # If current item is in delete range point to next available.
  324.     #
  325.     if {$_numitems > 1 &&
  326.     ([lsearch -exact [lrange $_items $first $last] [get]] != -1)} {
  327.     set nextAvail [_getNextItem $last]
  328.     }
  329.     
  330.     _setitems [lreplace $_items $first $last]
  331.     
  332.     #
  333.     # Make sure "nextAvail" is still in the list.
  334.     #
  335.     set index [lsearch -exact $_items $nextAvail]
  336.     _setItem [expr {$index != -1 ? $nextAvail : ""}]
  337. }
  338.  
  339. # ------------------------------------------------------------------
  340. # METHOD: disable index
  341. #
  342. # Disable a menu item in the option menu.  This will prevent the user
  343. # from being able to select this item from the menu.  This only effects
  344. # the state of the item in the menu, in other words, should the item
  345. # be the currently selected item, the user is responsible for 
  346. # determining this condition and taking appropriate action.
  347. # ------------------------------------------------------------------
  348. itcl::body iwidgets::Optionmenu::disable {index} {
  349.     set index [index $index]
  350.     $itk_component(popupMenu) entryconfigure $index -state disabled
  351. }
  352.  
  353. # ------------------------------------------------------------------
  354. # METHOD: enable index
  355. #
  356. # Enable a menu item in the option menu.  This will allow the user
  357. # to select this item from the menu.  
  358. # ------------------------------------------------------------------
  359. itcl::body iwidgets::Optionmenu::enable {index} {
  360.     set index [index $index]
  361.     $itk_component(popupMenu) entryconfigure $index -state normal
  362. }
  363.  
  364. # ------------------------------------------------------------------
  365. # METHOD: get
  366. #
  367. # Returns the current menu item.
  368. # ------------------------------------------------------------------
  369. itcl::body iwidgets::Optionmenu::get {{first "current"} {last ""}} {
  370.     if {"current" == $first} {
  371.         return $_currentItem
  372.     }
  373.  
  374.     set first [index $first]
  375.     if {"" == $last} {
  376.         return [$itk_component(popupMenu) entrycget $first -label]
  377.     }
  378.  
  379.     if {"end" == $last} {
  380.         set last [$itk_component(popupMenu) index end]
  381.     } else {
  382.         set last [index $last]
  383.     }
  384.     set rval ""
  385.     while {$first <= $last} {
  386.         lappend rval [$itk_component(popupMenu) entrycget $first -label]
  387.         incr first
  388.     }
  389.     return $rval
  390. }
  391.  
  392. # ------------------------------------------------------------------
  393. # METHOD: insert index string ?string?
  394. #
  395. # Insert an item in the popup menu.
  396. # ------------------------------------------------------------------
  397. itcl::body iwidgets::Optionmenu::insert {index string args} {
  398.     if {$index == "end"} {
  399.     set index $_numitems
  400.     } else {
  401.     set index [index $index]
  402.     }
  403.     set args [linsert $args 0 $string]
  404.     _setitems [eval linsert {$_items} $index $args]
  405.     return ""
  406. }
  407.  
  408. # ------------------------------------------------------------------
  409. # METHOD: select index
  410. #
  411. # Select an item from the popup menu to display on the menu label
  412. # button. 
  413. # ------------------------------------------------------------------
  414. itcl::body iwidgets::Optionmenu::select {index} {
  415.     set index [index $index]
  416.     if {$index > ($_numitems - 1)} {
  417.       incr index -1 
  418.     }
  419.     _setItem [lindex $_items $index]
  420. }
  421.  
  422. # ------------------------------------------------------------------
  423. # METHOD: popupMenu
  424. #
  425. # Evaluates the specified args against the popup menu component
  426. # and returns the result.
  427. # ------------------------------------------------------------------
  428. itcl::body iwidgets::Optionmenu::popupMenu {args} {
  429.     return [eval $itk_component(popupMenu) $args]    
  430. }
  431.  
  432. # ------------------------------------------------------------------
  433. # METHOD: sort mode
  434. #
  435. # Sort the current menu in either "ascending" or "descending" order.
  436. # ------------------------------------------------------------------
  437. itcl::body iwidgets::Optionmenu::sort {{mode "increasing"}} {
  438.     switch $mode {
  439.     ascending -
  440.     increasing {
  441.         _setitems [lsort -increasing $_items]
  442.     }
  443.     descending -
  444.     decreasing {
  445.         _setitems [lsort -decreasing $_items]
  446.     }
  447.     default {
  448.         error "bad sort argument \"$mode\": should be ascending,\
  449.             descending, increasing, or decreasing"
  450.     }
  451.     }
  452. }
  453.  
  454. # ------------------------------------------------------------------
  455. # PRIVATE METHOD: _buttonRelease
  456. #
  457. # Display the popup menu. Menu position is calculated.
  458. # ------------------------------------------------------------------
  459. itcl::body iwidgets::Optionmenu::_buttonRelease {time} {
  460.     if {(abs([expr $_postTime - $time])) <= $itk_option(-clicktime)} {
  461.         return -code break
  462.     }
  463. }
  464.  
  465. # ------------------------------------------------------------------
  466. # PRIVATE METHOD: _getNextItem index
  467. #
  468. # Allows either a string or index number to be passed in, and returns
  469. # the next item in the list in string format. Wrap around is automatic.
  470. # ------------------------------------------------------------------
  471. itcl::body iwidgets::Optionmenu::_getNextItem {index} {
  472.  
  473.     if {[incr index] >= $_numitems} {
  474.     set index 0   ;# wrap around
  475.     }
  476.     return [lindex $_items $index]
  477. }
  478.  
  479. # ------------------------------------------------------------------
  480. # PRIVATE METHOD: _next
  481. #
  482. # Sets the current option label to next item in list if that item is
  483. # not disbaled.
  484. # ------------------------------------------------------------------
  485. itcl::body iwidgets::Optionmenu::_next {} {
  486.     if {$itk_option(-state) != "normal"} {
  487.         return
  488.     }
  489.     set i [lsearch -exact $_items $_currentItem]
  490.     
  491.     for {set cnt 0} {$cnt < $_numitems} {incr cnt} {
  492.  
  493.         if {[incr i] >= $_numitems} {
  494.             set i 0
  495.         }
  496.         
  497.         if {[$itk_component(popupMenu) entrycget $i -state] != "disabled"} {
  498.             _setItem [lindex $_items $i]
  499.             break
  500.         }
  501.     }
  502. }
  503.  
  504. # ------------------------------------------------------------------
  505. # PRIVATE METHOD: _previous
  506. #
  507. # Sets the current option label to previous item in list if that 
  508. # item is not disbaled.
  509. # ------------------------------------------------------------------
  510. itcl::body iwidgets::Optionmenu::_previous {} {
  511.     if {$itk_option(-state) != "normal"} {
  512.         return
  513.     }
  514.  
  515.     set i [lsearch -exact $_items $_currentItem]
  516.     
  517.     for {set cnt 0} {$cnt < $_numitems} {incr cnt} {
  518.     set i [expr {$i - 1}]
  519.     
  520.     if {$i < 0} {
  521.         set i [expr {$_numitems - 1}]
  522.     }
  523.  
  524.     if {[$itk_component(popupMenu) entrycget $i -state] != "disabled"} {
  525.         _setItem [lindex $_items $i]
  526.         break
  527.     }
  528.     }
  529. }
  530.  
  531. # ------------------------------------------------------------------
  532. # PRIVATE METHOD: _postMenu time
  533. #
  534. # Display the popup menu. Menu position is calculated.
  535. # ------------------------------------------------------------------
  536. itcl::body iwidgets::Optionmenu::_postMenu {time} {
  537.     #
  538.     # Don't bother to post if menu is empty.
  539.     #
  540.     if {[llength $_items] > 0 && $itk_option(-state) == "normal"} {
  541.         set _postTime $time
  542.         set itemIndex [lsearch -exact $_items $_currentItem]
  543.  
  544.         set margin [expr {$itk_option(-borderwidth) \
  545.             + $itk_option(-highlightthickness)}]
  546.  
  547.         set x [expr {[winfo rootx $itk_component(menuBtn)] + $margin}]
  548.         set y [expr {[winfo rooty $itk_component(menuBtn)] \
  549.             - [$itk_component(popupMenu) yposition $itemIndex] + $margin}]
  550.  
  551.         tk_popup $itk_component(popupMenu) $x $y
  552.     }
  553. }
  554.  
  555. # ------------------------------------------------------------------
  556. # PRIVATE METHOD: _setItem
  557. #
  558. # Set the menu button label to item, then dismiss the popup menu.
  559. # Also check if item has been changed. If so, also call user-supplied
  560. # command.
  561. # ------------------------------------------------------------------
  562. itcl::body iwidgets::Optionmenu::_setItem {item} {
  563.     if {$_currentItem != $item} {
  564.         set _currentItem $item
  565.     if {[winfo ismapped $itk_component(hull)]} {
  566.         uplevel #0 $itk_option(-command)
  567.     }
  568.     }
  569. }
  570.  
  571. # ------------------------------------------------------------------
  572. # PRIVATE METHOD: _setitems items
  573. #
  574. # Create a list of items available on the menu. Used to create the
  575. # popup menu.
  576. # ------------------------------------------------------------------
  577. itcl::body iwidgets::Optionmenu::_setitems {items_} {
  578.  
  579.     #
  580.     # Delete the old menu entries, and set the new list of
  581.     # menu entries to those specified in "items_".
  582.     #
  583.     $itk_component(popupMenu) delete 0 last
  584.     set _items ""
  585.     set _numitems [llength $items_]
  586.  
  587.     #
  588.     # Clear the menu button label.
  589.     #
  590.     if {$_numitems == 0} {
  591.     _setItem ""
  592.     return
  593.     }
  594.  
  595.     set savedCurrentItem $_currentItem
  596.     
  597.     foreach opt $items_ {
  598.         lappend _items $opt
  599.         $itk_component(popupMenu) add command -label $opt \
  600.             -command [itcl::code $this _setItem $opt]
  601.     }
  602.     set first [lindex $_items 0]
  603.     
  604.     #
  605.     # Make sure "savedCurrentItem" is still in the list.
  606.     #
  607.     if {$first != ""} {
  608.         set i [lsearch -exact $_items $savedCurrentItem]
  609.     #-------------------------------------------------------------
  610.     # BEGIN BUG FIX: csmith (Chad Smith: csmith@adc.com), 11/18/99
  611.     #-------------------------------------------------------------
  612.     # The previous code fragment:
  613.     #   <select [expr {$i != -1 ? $savedCurrentItem : $first}]>
  614.     # is faulty because of exponential numbers.  For example,
  615.     # 2e-4 is numerically equal to 2e-04, but the string representation
  616.     # is of course different.  As a result, the select invocation
  617.     # fails, and an error message is printed.
  618.     #-------------------------------------------------------------
  619.     if {$i != -1} {
  620.       select $savedCurrentItem
  621.     } else {
  622.       select $first
  623.     }
  624.     #-------------------------------------------------------------
  625.     # END BUG FIX
  626.     #-------------------------------------------------------------
  627.     } else {
  628.     _setItem ""
  629.     }
  630.  
  631.     _setSize
  632. }
  633.  
  634. # ------------------------------------------------------------------
  635. # PRIVATE METHOD: _setSize ?when?
  636. #
  637. # Set the size of the option menu.  If "when" is "now", the change 
  638. # is applied immediately.  If it is "later" or it is not specified, 
  639. # then the change is applied later, when the application is idle.
  640. # ------------------------------------------------------------------
  641. itcl::body iwidgets::Optionmenu::_setSize {{when later}} {
  642.  
  643.     if {$when == "later"} {
  644.     if {$_calcSize == ""} {
  645.         set _calcSize [after idle [itcl::code $this _setSize now]]
  646.     }
  647.     return
  648.     }
  649.  
  650.     set margin [expr {2*($itk_option(-borderwidth) \
  651.         + $itk_option(-highlightthickness))}]
  652.  
  653.     if {"0" != $itk_option(-width)} {
  654.         set width $itk_option(-width)
  655.     } else {
  656.     set width [expr {[winfo reqwidth $itk_component(popupMenu)]+$margin+20}]
  657.     }
  658.     set height [winfo reqheight $itk_component(menuBtn)]
  659.     $itk_component(lwchildsite) configure -width $width -height $height
  660.  
  661.     set _calcSize ""
  662. }
  663.