PopMenu.tcl 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
  2. #
  3. # $Id: PopMenu.tcl,v 1.7 2004/03/28 02:44:57 hobbs Exp $
  4. #
  5. # PopMenu.tcl --
  6. #
  7. # This file implements the TixPopupMenu 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. global tkPriv
  16. if {![llength [info globals tkPriv]]} {
  17. tk::unsupported::ExposePrivateVariable tkPriv
  18. }
  19. #--------------------------------------------------------------------------
  20. # tkPriv elements used in this file:
  21. #
  22. # inMenubutton -
  23. #--------------------------------------------------------------------------
  24. #
  25. foreach fun {tkMenuUnpost tkMbButtonUp tkMbEnter tkMbPost} {
  26. if {![llength [info commands $fun]]} {
  27. tk::unsupported::ExposePrivateCommand $fun
  28. }
  29. }
  30. unset fun
  31. tixWidgetClass tixPopupMenu {
  32. -classname TixPopupMenu
  33. -superclass tixShell
  34. -method {
  35. bind post unbind
  36. }
  37. -flag {
  38. -buttons -installcolormap -postcmd -spring -state -title
  39. }
  40. -configspec {
  41. {-buttons buttons Buttons {{3 {Any}}}}
  42. {-installcolormap installColormap InstallColormap false}
  43. {-postcmd postCmd PostCmd ""}
  44. {-spring spring Spring 1 tixVerifyBoolean}
  45. {-state state State normal}
  46. {-cursor corsor Cursor arrow}
  47. }
  48. -static {
  49. -buttons
  50. }
  51. -default {
  52. {*Menu.tearOff 0}
  53. }
  54. }
  55. proc tixPopupMenu:InitWidgetRec {w} {
  56. upvar #0 $w data
  57. tixChainMethod $w InitWidgetRec
  58. set data(g:clients) ""
  59. }
  60. proc tixPopupMenu:ConstructWidget {w} {
  61. upvar #0 $w data
  62. tixChainMethod $w ConstructWidget
  63. wm overrideredirect $w 1
  64. wm withdraw $w
  65. set data(w:menubutton) [menubutton $w.menubutton -text $data(-title) \
  66. -menu $w.menubutton.menu -anchor w]
  67. set data(w:menu) [menu $w.menubutton.menu]
  68. pack $data(w:menubutton) -expand yes -fill both
  69. }
  70. proc tixPopupMenu:SetBindings {w} {
  71. upvar #0 $w data
  72. tixChainMethod $w SetBindings
  73. foreach elm $data(-buttons) {
  74. set btn [lindex $elm 0]
  75. foreach mod [lindex $elm 1] {
  76. tixBind TixPopupMenu:MB:$w <$mod-ButtonPress-$btn> \
  77. "tixPopupMenu:Unpost $w"
  78. tixBind TixPopupMenu:$w <$mod-ButtonPress-$btn> \
  79. "tixPopupMenu:post $w %W %x %y"
  80. }
  81. tixBind TixPopupMenu:MB:$w <ButtonRelease-$btn> \
  82. "tixPopupMenu:BtnRelease $w %X %Y"
  83. tixBind TixPopupMenu:M:$w <Unmap> \
  84. "tixPopupMenu:Unmap $w"
  85. tixBind TixPopupMenu:$w <ButtonRelease-$btn> \
  86. "tixPopupMenu:BtnRelease $w %X %Y"
  87. tixAddBindTag $data(w:menubutton) TixPopupMenu:MB:$w
  88. tixAddBindTag $data(w:menu) TixPopupMenu:M:$w
  89. }
  90. }
  91. #----------------------------------------------------------------------
  92. # PrivateMethods:
  93. #----------------------------------------------------------------------
  94. proc tixPopupMenu:Unpost {w} {
  95. upvar #0 $w data
  96. catch {
  97. tkMenuUnpost ""
  98. }
  99. # tkMbButtonUp $data(w:menubutton)
  100. }
  101. proc tixPopupMenu:BtnRelease {w rootX rootY} {
  102. upvar #0 $w data
  103. set cW [winfo containing -displayof $w $rootX $rootY]
  104. if {$data(-spring)} {
  105. tixPopupMenu:Unpost $w
  106. }
  107. }
  108. proc tixPopupMenu:Unmap {w} {
  109. upvar #0 $w data
  110. wm withdraw $w
  111. }
  112. proc tixPopupMenu:Destructor {w} {
  113. upvar #0 $w data
  114. foreach client $data(g:clients) {
  115. if {[winfo exists $client]} {
  116. tixDeleteBindTag $client TixPopupMenu:$w
  117. }
  118. }
  119. # delete the extra bindings
  120. #
  121. foreach tag [list TixPopupMenu:MB:$w TixPopupMenu:M:$w] {
  122. foreach e [bind $tag] {
  123. bind $tag $e ""
  124. }
  125. }
  126. tixChainMethod $w Destructor
  127. }
  128. proc tixPopupMenu:config-title {w value} {
  129. upvar #0 $w data
  130. $data(w:menubutton) config -text $value
  131. }
  132. #----------------------------------------------------------------------
  133. # PublicMethods:
  134. #----------------------------------------------------------------------
  135. proc tixPopupMenu:bind {w args} {
  136. upvar #0 $w data
  137. foreach client $args {
  138. if {[lsearch $data(g:clients) $client] == -1} {
  139. lappend data(g:clients) $client
  140. tixAppendBindTag $client TixPopupMenu:$w
  141. }
  142. }
  143. }
  144. proc tixPopupMenu:unbind {w args} {
  145. upvar #0 $w data
  146. foreach client $args {
  147. if {[winfo exists $client]} {
  148. set index [lsearch $data(g:clients) $client]
  149. if {$index != -1} {
  150. tixDeleteBindTag $client TixPopupMenu:$w
  151. set data(g:clients) [lreplace $data(g:clients) $index $index]
  152. }
  153. }
  154. }
  155. }
  156. proc tixPopupMenu:post {w client x y} {
  157. upvar #0 $w data
  158. global tkPriv
  159. if {$data(-state) == "disabled"} {
  160. return
  161. }
  162. set rootx [expr $x + [winfo rootx $client]]
  163. set rooty [expr $y + [winfo rooty $client]]
  164. if {$data(-postcmd) != ""} {
  165. set ret [tixEvalCmdBinding $w $data(-postcmd) "" $rootx $rooty]
  166. if {![tixGetBoolean $ret]} {
  167. return
  168. }
  169. }
  170. if {[string is true -strict $data(-installcolormap)]} {
  171. wm colormapwindows . $w
  172. }
  173. set menuWidth [winfo reqwidth $data(w:menu)]
  174. set width [winfo reqwidth $w]
  175. set height [winfo reqheight $w]
  176. if {$width < $menuWidth} {
  177. set width $menuWidth
  178. }
  179. set wx $rootx
  180. set wy $rooty
  181. # trick: the following lines allow the popup menu
  182. # acquire a stable width and height when it is finally
  183. # put on the visible screen. Advoid flashing
  184. #
  185. wm geometry $w +10000+10000
  186. wm deiconify $w
  187. raise $w
  188. update
  189. wm geometry $w ${width}x${height}+${wx}+${wy}
  190. update
  191. tkMbEnter $data(w:menubutton)
  192. tkMbPost $tkPriv(inMenubutton) $rootx $rooty
  193. }