Utils.tcl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
  2. #
  3. # $Id: Utils.tcl,v 1.4 2004/03/28 02:44:57 hobbs Exp $
  4. #
  5. # Util.tcl --
  6. #
  7. # The Tix utility commands. Some of these commands are
  8. # replacement of or extensions to the existing TK
  9. # commands. Occasionaly, you have to use the commands inside
  10. # this file instead of thestandard TK commands to make your
  11. # applicatiion work better with Tix. Please read the
  12. # documentations (programmer's guide, man pages) for information
  13. # about these utility commands.
  14. #
  15. # Copyright (c) 1993-1999 Ioi Kim Lam.
  16. # Copyright (c) 2000-2001 Tix Project Group.
  17. # Copyright (c) 2004 ActiveState
  18. #
  19. # See the file "license.terms" for information on usage and redistribution
  20. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  21. #
  22. #
  23. # kludge: should be able to handle all kinds of flags
  24. # now only handles "-flag value" pairs.
  25. #
  26. proc tixHandleArgv {p_argv p_options validFlags} {
  27. upvar $p_options opt
  28. upvar $p_argv argv
  29. set old_argv $argv
  30. set argv ""
  31. foreac {flag value} $old_argv {
  32. if {[lsearch $validFlags $flag] != -1} {
  33. # The caller will handle this option exclusively
  34. # It won't be added back to the original arglist
  35. #
  36. eval $opt($flag,action) $value
  37. } else {
  38. # The caller does not handle this option
  39. #
  40. lappend argv $flag
  41. lappend argv $value
  42. }
  43. }
  44. }
  45. #-----------------------------------------------------------------------
  46. # tixDisableAll -
  47. #
  48. # Disable all members in a sub widget tree
  49. #
  50. proc tixDisableAll {w} {
  51. foreach x [tixDescendants $w] {
  52. catch {$x config -state disabled}
  53. }
  54. }
  55. #----------------------------------------------------------------------
  56. # tixEnableAll -
  57. #
  58. # enable all members in a sub widget tree
  59. #
  60. proc tixEnableAll {w} {
  61. foreach x [tixDescendants $w] {
  62. catch {$x config -state normal}
  63. }
  64. }
  65. #----------------------------------------------------------------------
  66. # tixDescendants -
  67. #
  68. # Return a list of all the member of a widget subtree, including
  69. # the tree's root widget.
  70. #
  71. proc tixDescendants {parent} {
  72. set des ""
  73. lappend des $parent
  74. foreach w [winfo children $parent] {
  75. foreach x [tixDescendants $w] {
  76. lappend des $x
  77. }
  78. }
  79. return $des
  80. }
  81. #----------------------------------------------------------------------
  82. # tixTopLevel -
  83. #
  84. # Create a toplevel widget and unmap it immediately. This will ensure
  85. # that this toplevel widgets will not be popped up prematurely when you
  86. # create Tix widgets inside it.
  87. #
  88. # "tixTopLevel" also provide options for you to specify the appearance
  89. # and behavior of this toplevel.
  90. #
  91. #
  92. #
  93. proc tixTopLevel {w args} {
  94. set opt (-geometry) ""
  95. set opt (-minsize) ""
  96. set opt (-maxsize) ""
  97. set opt (-width) ""
  98. set opt (-height) ""
  99. eval [linsert $args 0 toplevel $w]
  100. wm withdraw $w
  101. }
  102. # This is a big kludge
  103. #
  104. # Substitutes all [...] and $.. in the string in $args
  105. #
  106. proc tixInt_Expand {args} {
  107. return $args
  108. }
  109. # Print out all the config options of a widget
  110. #
  111. proc tixPConfig {w} {
  112. puts [join [lsort [$w config]] \n]
  113. }
  114. proc tixAppendBindTag {w tag} {
  115. bindtags $w [concat [bindtags $w] $tag]
  116. }
  117. proc tixAddBindTag {w tag} {
  118. bindtags $w [concat $tag [bindtags $w] ]
  119. }
  120. proc tixSubwidgetRef {sub} {
  121. return $::tixSRef($sub)
  122. }
  123. proc tixSubwidgetRetCreate {sub ref} {
  124. set ::tixSRef($sub) $ref
  125. }
  126. proc tixSubwidgetRetDelete {sub} {
  127. catch {unset ::tixSRef($sub)}
  128. }
  129. proc tixListboxGetCurrent {listbox} {
  130. return [tixEvent flag V]
  131. }
  132. # tixSetMegaWidget --
  133. #
  134. # Associate a subwidget with its mega widget "owner". This is mainly
  135. # used when we add a new bindtag to a subwidget and we need to find out
  136. # the name of the mega widget inside the binding.
  137. #
  138. proc tixSetMegaWidget {w mega {type any}} {
  139. set ::tixMega($type,$w) $mega
  140. }
  141. proc tixGetMegaWidget {w {type any}} {
  142. return $::tixMega($type,$w)
  143. }
  144. proc tixUnsetMegaWidget {w} {
  145. if {[info exists ::tixMega($w)]} { unset ::tixMega($w) }
  146. }
  147. # tixBusy : display busy cursors on a window
  148. #
  149. #
  150. # Should flush the event queue (but not do any idle tasks) before blocking
  151. # the target window (I am not sure if it is aready doing so )
  152. #
  153. # ToDo: should take some additional windows to raise
  154. #
  155. proc tixBusy {w flag {focuswin ""}} {
  156. if {[info command tixInputOnly] == ""} {
  157. return
  158. }
  159. global tixBusy
  160. set toplevel [winfo toplevel $w]
  161. if {![info exists tixBusy(cursor)]} {
  162. set tixBusy(cursor) watch
  163. # set tixBusy(cursor) "[tix getbitmap hourglass] \
  164. # [string range [tix getbitmap hourglass.mask] 1 end]\
  165. # black white"
  166. }
  167. if {$toplevel eq "."} {
  168. set inputonly0 .__tix__busy0
  169. set inputonly1 .__tix__busy1
  170. set inputonly2 .__tix__busy2
  171. set inputonly3 .__tix__busy3
  172. } else {
  173. set inputonly0 $toplevel.__tix__busy0
  174. set inputonly1 $toplevel.__tix__busy1
  175. set inputonly2 $toplevel.__tix__busy2
  176. set inputonly3 $toplevel.__tix__busy3
  177. }
  178. if {![winfo exists $inputonly0]} {
  179. for {set i 0} {$i < 4} {incr i} {
  180. tixInputOnly [set inputonly$i] -cursor $tixBusy(cursor)
  181. }
  182. }
  183. if {$flag eq "on"} {
  184. if {$focuswin != "" && [winfo id $focuswin] != 0} {
  185. if {[info exists tixBusy($focuswin,oldcursor)]} {
  186. return
  187. }
  188. set tixBusy($focuswin,oldcursor) [$focuswin cget -cursor]
  189. $focuswin config -cursor $tixBusy(cursor)
  190. set x1 [expr {[winfo rootx $focuswin]-[winfo rootx $toplevel]}]
  191. set y1 [expr {[winfo rooty $focuswin]-[winfo rooty $toplevel]}]
  192. set W [winfo width $focuswin]
  193. set H [winfo height $focuswin]
  194. set x2 [expr {$x1 + $W}]
  195. set y2 [expr {$y1 + $H}]
  196. if {$y1 > 0} {
  197. tixMoveResizeWindow $inputonly0 0 0 10000 $y1
  198. }
  199. if {$x1 > 0} {
  200. tixMoveResizeWindow $inputonly1 0 0 $x1 10000
  201. }
  202. tixMoveResizeWindow $inputonly2 0 $y2 10000 10000
  203. tixMoveResizeWindow $inputonly3 $x2 0 10000 10000
  204. for {set i 0} {$i < 4} {incr i} {
  205. tixMapWindow [set inputonly$i]
  206. tixRaiseWindow [set inputonly$i]
  207. }
  208. tixFlushX $w
  209. } else {
  210. tixMoveResizeWindow $inputonly0 0 0 10000 10000
  211. tixMapWindow $inputonly0
  212. tixRaiseWindow $inputonly0
  213. }
  214. } else {
  215. tixUnmapWindow $inputonly0
  216. tixUnmapWindow $inputonly1
  217. tixUnmapWindow $inputonly2
  218. tixUnmapWindow $inputonly3
  219. if {$focuswin != "" && [winfo id $focuswin] != 0} {
  220. if {[info exists tixBusy($focuswin,oldcursor)]} {
  221. $focuswin config -cursor $tixBusy($focuswin,oldcursor)
  222. if {[info exists tixBusy($focuswin,oldcursor)]} {
  223. unset tixBusy($focuswin,oldcursor)
  224. }
  225. }
  226. }
  227. }
  228. }
  229. proc tixOptionName {w} {
  230. return [string range $w 1 end]
  231. }
  232. proc tixSetSilent {chooser value} {
  233. $chooser config -disablecallback true
  234. $chooser config -value $value
  235. $chooser config -disablecallback false
  236. }
  237. # This command is useful if you want to ingore the arguments
  238. # passed by the -command or -browsecmd options of the Tix widgets. E.g
  239. #
  240. # tixFileSelectDialog .c -command "puts foo; tixBreak"
  241. #
  242. #
  243. proc tixBreak {args} {}
  244. #----------------------------------------------------------------------
  245. # tixDestroy -- deletes a Tix class object (not widget classes)
  246. #----------------------------------------------------------------------
  247. proc tixDestroy {w} {
  248. upvar #0 $w data
  249. set destructor ""
  250. if {[info exists data(className)]} {
  251. catch {
  252. set destructor [tixGetMethod $w $data(className) Destructor]
  253. }
  254. }
  255. if {$destructor != ""} {
  256. $destructor $w
  257. }
  258. catch {rename $w ""}
  259. catch {unset data}
  260. return ""
  261. }
  262. proc tixPushGrab {args} {
  263. global tix_priv
  264. if {![info exists tix_priv(grab-list)]} {
  265. set tix_priv(grab-list) ""
  266. set tix_priv(grab-mode) ""
  267. set tix_priv(grab-nopush) ""
  268. }
  269. set len [llength $args]
  270. if {$len == 1} {
  271. set opt ""
  272. set w [lindex $args 0]
  273. } elseif {$len == 2} {
  274. set opt [lindex $args 0]
  275. set w [lindex $args 1]
  276. } else {
  277. error "wrong # of arguments: tixPushGrab ?-global? window"
  278. }
  279. # Not everyone will call tixPushGrab. If someone else has a grab already
  280. # save that one as well, so that we can restore that later
  281. #
  282. set last [lindex $tix_priv(grab-list) end]
  283. set current [grab current $w]
  284. if {$current ne "" && $current ne $last} {
  285. # Someone called "grab" directly
  286. #
  287. lappend tix_priv(grab-list) $current
  288. lappend tix_priv(grab-mode) [grab status $current]
  289. lappend tix_priv(grab-nopush) 1
  290. }
  291. # Now push myself into the stack
  292. #
  293. lappend tix_priv(grab-list) $w
  294. lappend tix_priv(grab-mode) $opt
  295. lappend tix_priv(grab-nopush) 0
  296. if {$opt eq "-global"} {
  297. grab -global $w
  298. } else {
  299. grab $w
  300. }
  301. }
  302. proc tixPopGrab {} {
  303. global tix_priv
  304. if {![info exists tix_priv(grab-list)]} {
  305. set tix_priv(grab-list) ""
  306. set tix_priv(grab-mode) ""
  307. set tix_priv(grab-nopush) ""
  308. }
  309. set len [llength $tix_priv(grab-list)]
  310. if {$len <= 0} {
  311. error "no window is grabbed by tixGrab"
  312. }
  313. set w [lindex $tix_priv(grab-list) end]
  314. grab release $w
  315. if {$len > 1} {
  316. set tix_priv(grab-list) [lrange $tix_priv(grab-list) 0 end-1]
  317. set tix_priv(grab-mode) [lrange $tix_priv(grab-mode) 0 end-1]
  318. set tix_priv(grab-nopush) [lrange $tix_priv(grab-nopush) 0 end-1]
  319. set w [lindex $tix_priv(grab-list) end]
  320. set m [lindex $tix_priv(grab-list) end]
  321. set np [lindex $tix_priv(grab-nopush) end]
  322. if {$np == 1} {
  323. # We have a grab set by "grab"
  324. #
  325. set len [llength $tix_priv(grab-list)]
  326. if {$len > 1} {
  327. set tix_priv(grab-list) [lrange $tix_priv(grab-list) 0 end-1]
  328. set tix_priv(grab-mode) [lrange $tix_priv(grab-mode) 0 end-1]
  329. set tix_priv(grab-nopush) \
  330. [lrange $tix_priv(grab-nopush) 0 end-1]
  331. } else {
  332. set tix_priv(grab-list) ""
  333. set tix_priv(grab-mode) ""
  334. set tix_priv(grab-nopush) ""
  335. }
  336. }
  337. if {$m == "-global"} {
  338. grab -global $w
  339. } else {
  340. grab $w
  341. }
  342. } else {
  343. set tix_priv(grab-list) ""
  344. set tix_priv(grab-mode) ""
  345. set tix_priv(grab-nopush) ""
  346. }
  347. }
  348. proc tixWithinWindow {wid rootX rootY} {
  349. set wc [winfo containing $rootX $rootY]
  350. if {$wid eq $wc} { return 1 }
  351. # no see if it is an enclosing parent
  352. set rx1 [winfo rootx $wid]
  353. set ry1 [winfo rooty $wid]
  354. set rw [winfo width $wid]
  355. set rh [winfo height $wid]
  356. set rx2 [expr {$rx1+$rw}]
  357. set ry2 [expr {$ry1+$rh}]
  358. if {$rootX >= $rx1 && $rootX < $rx2 && $rootY >= $ry1 && $rootY < $ry2} {
  359. return 1
  360. } else {
  361. return 0
  362. }
  363. }
  364. proc tixWinWidth {w} {
  365. set W [winfo width $w]
  366. set bd [expr {[$w cget -bd] + [$w cget -highlightthickness]}]
  367. return [expr {$W - 2*$bd}]
  368. }
  369. proc tixWinHeight {w} {
  370. set H [winfo height $w]
  371. set bd [expr {[$w cget -bd] + [$w cget -highlightthickness]}]
  372. return [expr {$H - 2*$bd}]
  373. }
  374. # junk?
  375. #
  376. proc tixWinCmd {w} {
  377. return [winfo command $w]
  378. }