OptMenu.tcl 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
  2. #
  3. # $Id: OptMenu.tcl,v 1.3 2001/12/09 05:04:02 idiscovery Exp $
  4. #
  5. # OptMenu.tcl --
  6. #
  7. # This file implements the TixOptionMenu widget.
  8. #
  9. # Copyright (c) 1993-1999 Ioi Kim Lam.
  10. # Copyright (c) 2000-2001 Tix Project Group.
  11. #
  12. # See the file "license.terms" for information on usage and redistribution
  13. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  14. #
  15. tixWidgetClass tixOptionMenu {
  16. -classname TixOptionMenu
  17. -superclass tixLabelWidget
  18. -method {
  19. add delete disable enable entrycget entryconfigure entries
  20. }
  21. -flag {
  22. -command -disablecallback -dynamicgeometry -value -variable
  23. -validatecmd -state
  24. }
  25. -forcecall {
  26. -variable -state
  27. }
  28. -configspec {
  29. {-command command Command ""}
  30. {-disablecallback disableCallback DisableCallback 0 tixVerifyBoolean}
  31. {-dynamicgeometry dynamicGeometry DynamicGeometry 0 tixVerifyBoolean}
  32. {-state state State normal}
  33. {-value value Value ""}
  34. {-validatecmd validateCmd ValidateCmd ""}
  35. {-variable variable Variable ""}
  36. }
  37. -default {
  38. {.highlightThickness 0}
  39. {.takeFocus 0}
  40. {.frame.menubutton.relief raised}
  41. {.frame.menubutton.borderWidth 2}
  42. {.frame.menubutton.anchor w}
  43. {.frame.menubutton.highlightThickness 2}
  44. {.frame.menubutton.takeFocus 1}
  45. }
  46. }
  47. proc tixOptionMenu:InitWidgetRec {w} {
  48. upvar #0 $w data
  49. tixChainMethod $w InitWidgetRec
  50. set data(nItems) 0
  51. set data(items) ""
  52. set data(posted) 0
  53. set data(varInited) 0
  54. set data(maxWidth) 0
  55. }
  56. proc tixOptionMenu:ConstructFramedWidget {w frame} {
  57. upvar #0 $w data
  58. tixChainMethod $w ConstructFramedWidget $frame
  59. set data(w:menubutton) [menubutton $frame.menubutton -indicatoron 1]
  60. set data(w:menu) [menu $frame.menubutton.menu -tearoff 0]
  61. pack $data(w:menubutton) -side left -expand yes -fill both
  62. $data(w:menubutton) config -menu $data(w:menu)
  63. bind $data(w:menubutton) <Up> [bind Menubutton <space>]
  64. bind $data(w:menubutton) <Down> [bind Menubutton <space>]
  65. tixSetMegaWidget $data(w:menubutton) $w
  66. }
  67. proc tixOptionMenu:SetBindings {w} {
  68. upvar #0 $w data
  69. tixChainMethod $w SetBindings
  70. }
  71. #----------------------------------------------------------------------
  72. # Private methods
  73. #----------------------------------------------------------------------
  74. proc tixOptionMenu:Invoke {w name} {
  75. upvar #0 $w data
  76. if {"$data(-state)" == "normal"} {
  77. tixOptionMenu:SetValue $w $name
  78. }
  79. }
  80. proc tixOptionMenu:SetValue {w value {noUpdate 0}} {
  81. upvar #0 $w data
  82. if {$data(-validatecmd) != ""} {
  83. set value [tixEvalCmdBinding $w $data(-validatecmd) "" $value]
  84. }
  85. set name $value
  86. if {$name == "" || [info exists data(varInited)]} {
  87. # variable may contain a bogus value
  88. if {![info exists data($name,index)]} {
  89. set data(-value) ""
  90. tixVariable:UpdateVariable $w
  91. $data(w:menubutton) config -text ""
  92. return
  93. }
  94. }
  95. if {[info exists data($name,index)]} {
  96. $data(w:menubutton) config -text $data($name,label)
  97. set data(-value) $value
  98. if {! $noUpdate} {
  99. tixVariable:UpdateVariable $w
  100. }
  101. if {$data(-command) != "" && !$data(-disablecallback)} {
  102. if {![info exists data(varInited)]} {
  103. set bind(specs) ""
  104. tixEvalCmdBinding $w $data(-command) bind $value
  105. }
  106. }
  107. } else {
  108. error "item \"$value\" does not exist"
  109. }
  110. }
  111. proc tixOptionMenu:SetMaxWidth {w} {
  112. upvar #0 $w data
  113. foreach name $data(items) {
  114. set len [string length $data($name,label)]
  115. if {$data(maxWidth) < $len} {
  116. set data(maxWidth) $len
  117. }
  118. }
  119. if {$data(maxWidth) > 0} {
  120. $data(w:menubutton) config -width $data(maxWidth)
  121. }
  122. }
  123. #----------------------------------------------------------------------
  124. # Configuration
  125. #----------------------------------------------------------------------
  126. proc tixOptionMenu:config-state {w value} {
  127. upvar #0 $w data
  128. if {![info exists data(w:label)]} {
  129. return
  130. }
  131. if {$value == "normal"} {
  132. catch {
  133. $data(w:label) config -fg \
  134. [$data(w:menubutton) cget -foreground]
  135. }
  136. $data(w:menubutton) config -state $value
  137. } else {
  138. catch {
  139. $data(w:label) config -fg \
  140. [$data(w:menubutton) cget -disabledforeground]
  141. }
  142. $data(w:menubutton) config -state $value
  143. }
  144. }
  145. proc tixOptionMenu:config-value {w value} {
  146. upvar #0 $w data
  147. tixOptionMenu:SetValue $w $value
  148. # This will tell the Intrinsics: "Please use this value"
  149. # because "value" might be altered by SetValues
  150. #
  151. return $data(-value)
  152. }
  153. proc tixOptionMenu:config-variable {w arg} {
  154. upvar #0 $w data
  155. if {[tixVariable:ConfigVariable $w $arg]} {
  156. # The value of data(-value) is changed if tixVariable:ConfigVariable
  157. # returns true
  158. tixOptionMenu:SetValue $w $data(-value) 1
  159. }
  160. catch {
  161. unset data(varInited)
  162. }
  163. set data(-variable) $arg
  164. }
  165. #----------------------------------------------------------------------
  166. # Public Methdos
  167. #----------------------------------------------------------------------
  168. proc tixOptionMenu:add {w type name args} {
  169. upvar #0 $w data
  170. if {[info exists data($name,index)]} {
  171. error "item $name already exists in the option menu $w"
  172. }
  173. case $type {
  174. "command" {
  175. set validOptions {
  176. -command -label
  177. }
  178. set opt(-command) ""
  179. set opt(-label) $name
  180. tixHandleOptions -nounknown opt $validOptions $args
  181. if {$opt(-command) != ""} {
  182. error "option -command cannot be specified"
  183. }
  184. # Create a new item inside the menu
  185. #
  186. eval $data(w:menu) add command $args \
  187. [list -label $opt(-label) \
  188. -command "tixOptionMenu:Invoke $w \{$name\}"]
  189. set index $data(nItems)
  190. # Store info about this item
  191. #
  192. set data($index,name) $name
  193. set data($name,type) cmd
  194. set data($name,label) $opt(-label)
  195. set data($name,index) $index
  196. if {$index == 0} {
  197. $data(w:menubutton) config -text $data($name,label)
  198. tixOptionMenu:SetValue $w $name
  199. }
  200. incr data(nItems)
  201. lappend data(items) $name
  202. if $data(-dynamicgeometry) {
  203. tixOptionMenu:SetMaxWidth $w
  204. }
  205. }
  206. "separator" {
  207. $data(w:menu) add separator
  208. set index $data(nItems)
  209. # Store info about this item
  210. #
  211. set data($index,name) $name
  212. set data($name,type) sep
  213. set data($name,label) ""
  214. set data($name,index) $index
  215. incr data(nItems)
  216. lappend data(items) $name
  217. }
  218. default {
  219. error "only types \"separator\" and \"command\" are allowed"
  220. }
  221. }
  222. return ""
  223. }
  224. proc tixOptionMenu:delete {w item} {
  225. upvar #0 $w data
  226. if {![info exists data($item,index)]} {
  227. error "item $item does not exist in $w"
  228. }
  229. # Rehash the item list
  230. set newItems ""
  231. set oldIndex 0
  232. set newIndex 0
  233. foreach name $data(items) {
  234. if {$item == $name} {
  235. unset data($name,label)
  236. unset data($name,index)
  237. unset data($name,type)
  238. $data(w:menu) delete $oldIndex
  239. } else {
  240. set data($name,index) $newIndex
  241. set data($newIndex,name) $name
  242. incr newIndex
  243. lappend newItems $name
  244. }
  245. incr oldIndex
  246. }
  247. incr oldIndex -1; unset data($oldIndex,name)
  248. set data(nItems) $newIndex
  249. set data(items) $newItems
  250. if {$data(-value) == $item} {
  251. set newVal ""
  252. foreach item $data(items) {
  253. if {$data($item,type) == "cmd"} {
  254. set newVal $item
  255. }
  256. }
  257. tixOptionMenu:SetValue $w $newVal
  258. }
  259. return ""
  260. }
  261. proc tixOptionMenu:disable {w item} {
  262. upvar #0 $w data
  263. if {![info exists data($item,index)]} {
  264. error "item $item does not exist in $w"
  265. } else {
  266. catch {$data(w:menu) entryconfig $data($item,index) -state disabled}
  267. }
  268. }
  269. proc tixOptionMenu:enable {w item} {
  270. upvar #0 $w data
  271. if {![info exists data($item,index)]} {
  272. error "item $item does not exist in $w"
  273. } else {
  274. catch {$data(w:menu) entryconfig $data($item,index) -state normal}
  275. }
  276. }
  277. proc tixOptionMenu:entryconfigure {w item args} {
  278. upvar #0 $w data
  279. if {![info exists data($item,index)]} {
  280. error "item $item does not exist in $w"
  281. } else {
  282. return [eval $data(w:menu) entryconfig $data($item,index) $args]
  283. }
  284. }
  285. proc tixOptionMenu:entrycget {w item arg} {
  286. upvar #0 $w data
  287. if {![info exists data($item,index)]} {
  288. error "item $item does not exist in $w"
  289. } else {
  290. return [$data(w:menu) entrycget $data($item,index) $arg]
  291. }
  292. }
  293. proc tixOptionMenu:entries {w} {
  294. upvar #0 $w data
  295. return $data(items)
  296. }
  297. proc tixOptionMenu:Destructor {w} {
  298. tixVariable:DeleteVariable $w
  299. # Chain this to the superclass
  300. #
  301. tixChainMethod $w Destructor
  302. }
  303. #----------------------------------------------------------------------
  304. # Obsolete
  305. # These have been replaced by new commands in Tk 4.0
  306. #
  307. proc tixOptionMenu:Post {w} {
  308. upvar #0 $w data
  309. set rootx [winfo rootx $data(w:frame)]
  310. set rooty [winfo rooty $data(w:frame)]
  311. # adjust for the border of the menu and frame
  312. #
  313. incr rootx [lindex [$data(w:menu) config -border] 4]
  314. incr rooty [lindex [$data(w:frame) config -border] 4]
  315. incr rooty [lindex [$data(w:menu) config -border] 4]
  316. set value $data(-value)
  317. set y [$data(w:menu) yposition $data($value,index)]
  318. $data(w:menu) post $rootx [expr $rooty - $y]
  319. $data(w:menu) activate $data($value,index)
  320. grab -global $data(w:menubutton)
  321. set data(posted) 1
  322. }