SWidget.tcl 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
  2. #
  3. # $Id: SWidget.tcl,v 1.5 2002/01/24 09:13:58 idiscovery Exp $
  4. #
  5. # SWidget.tcl --
  6. #
  7. # tixScrolledWidget: virtual base class. Do not instantiate
  8. # This is the core class for all scrolled widgets.
  9. #
  10. # Copyright (c) 1993-1999 Ioi Kim Lam.
  11. # Copyright (c) 2000-2001 Tix Project Group.
  12. #
  13. # See the file "license.terms" for information on usage and redistribution
  14. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  15. #
  16. tixWidgetClass tixScrolledWidget {
  17. -virtual true
  18. -classname TixScrolledWidget
  19. -superclass tixPrimitive
  20. -method {
  21. }
  22. -flag {
  23. -scrollbar -scrollbarspace
  24. }
  25. -configspec {
  26. {-scrollbar scrollbar Scrollbar both}
  27. {-scrollbarspace scrollbarSpace ScrollbarSpace {both}}
  28. {-sizebox sizeBox SizeBox 0}
  29. }
  30. }
  31. proc tixScrolledWidget:InitWidgetRec {w} {
  32. upvar #0 $w data
  33. tixChainMethod $w InitWidgetRec
  34. set data(x,first) 0
  35. set data(x,last) 0
  36. set data(y,first) 0
  37. set data(y,last) 0
  38. set data(lastSpec) ""
  39. set data(lastMW) ""
  40. set data(lastMH) ""
  41. set data(lastScbW) ""
  42. set data(lastScbH) ""
  43. set data(repack) 0
  44. set data(counter) 0
  45. set data(vsbPadY) 0
  46. set data(hsbPadX) 0
  47. }
  48. proc tixScrolledWidget:SetBindings {w} {
  49. upvar #0 $w data
  50. tixChainMethod $w SetBindings
  51. tixManageGeometry $data(pw:client) "tixScrolledWidget:ClientGeomProc $w"
  52. bind $data(pw:client) <Configure> \
  53. [list tixScrolledWidget:ClientGeomProc $w "" $data(pw:client)]
  54. tixManageGeometry $data(w:hsb) "tixScrolledWidget:ClientGeomProc $w"
  55. bind $data(w:hsb) <Configure> \
  56. [list tixScrolledWidget:ClientGeomProc $w "" $data(w:hsb)]
  57. tixManageGeometry $data(w:vsb) "tixScrolledWidget:ClientGeomProc $w"
  58. bind $data(w:vsb) <Configure> \
  59. [list tixScrolledWidget:ClientGeomProc $w "" $data(w:vsb)]
  60. bind $w <Configure> "tixScrolledWidget:MasterGeomProc $w"
  61. tixWidgetDoWhenIdle tixScrolledWidget:Repack $w
  62. set data(repack) 1
  63. }
  64. proc tixScrolledWidget:config-scrollbar {w value} {
  65. upvar #0 $w data
  66. global tcl_platform
  67. if {[lindex $value 0] == "auto"} {
  68. foreach xspec [lrange $value 1 end] {
  69. case $xspec {
  70. {+x -x +y -y} {}
  71. default {
  72. error "bad -scrollbar value \"$value\""
  73. }
  74. }
  75. }
  76. } else {
  77. case $value in {
  78. {none x y both} {}
  79. default {
  80. error "bad -scrollbar value \"$value\""
  81. }
  82. }
  83. }
  84. if {$data(-sizebox) && $tcl_platform(platform) == "windows"} {
  85. set data(-scrollbar) both
  86. }
  87. if {$data(repack) == 0} {
  88. set data(repack) 1
  89. tixWidgetDoWhenIdle tixScrolledWidget:Repack $w
  90. }
  91. }
  92. proc tixScrolledWidget:config-scrollbarspace {w value} {
  93. upvar #0 $w data
  94. if {$data(repack) == 0} {
  95. set data(repack) 1
  96. tixWidgetDoWhenIdle tixScrolledWidget:Repack $w
  97. }
  98. }
  99. proc tixScrolledWidget:config-sizebox {w value} {
  100. error "unimplemented"
  101. }
  102. #----------------------------------------------------------------------
  103. #
  104. # Scrollbar calculations
  105. #
  106. #----------------------------------------------------------------------
  107. proc tixScrolledWidget:ClientGeomProc {w type client} {
  108. upvar #0 $w data
  109. if {$data(repack) == 0} {
  110. set data(repack) 1
  111. tixWidgetDoWhenIdle tixScrolledWidget:Repack $w
  112. }
  113. }
  114. proc tixScrolledWidget:MasterGeomProc {w} {
  115. upvar #0 $w data
  116. if {$data(repack) == 0} {
  117. set data(repack) 1
  118. tixWidgetDoWhenIdle tixScrolledWidget:Repack $w
  119. }
  120. }
  121. proc tixScrolledWidget:Configure {w} {
  122. if {![winfo exists $w]} {
  123. return
  124. }
  125. upvar #0 $w data
  126. if {$data(repack) == 0} {
  127. set data(repack) 1
  128. tixWidgetDoWhenIdle tixScrolledWidget:Repack $w
  129. }
  130. }
  131. proc tixScrolledWidget:ScrollCmd {w scrollbar axis first last} {
  132. upvar #0 $w data
  133. $scrollbar set $first $last
  134. }
  135. # Show or hide the scrollbars as required.
  136. #
  137. # spec: 00 = need none
  138. # spec: 01 = need y
  139. # spec: 10 = need x
  140. # spec: 11 = need xy
  141. #
  142. proc tixScrolledWidget:Repack {w} {
  143. tixCallMethod $w RepackHook
  144. }
  145. proc tixScrolledWidget:RepackHook {w} {
  146. upvar #0 $w data
  147. global tcl_platform
  148. if {![winfo exists $w]} {
  149. # This was generated by the <Destroy> event
  150. #
  151. return
  152. }
  153. set client $data(pw:client)
  154. # Calculate the size of the master
  155. #
  156. set mreqw [winfo reqwidth $w]
  157. set mreqh [winfo reqheight $w]
  158. set creqw [winfo reqwidth $client]
  159. set creqh [winfo reqheight $client]
  160. set scbW [winfo reqwidth $w.vsb]
  161. set scbH [winfo reqheight $w.hsb]
  162. case $data(-scrollbarspace) {
  163. "x" {
  164. incr creqh $scbH
  165. }
  166. "y" {
  167. incr creqw $scbW
  168. }
  169. "both" {
  170. incr creqw $scbW
  171. incr creqh $scbH
  172. }
  173. }
  174. if {$data(-width) != 0} {
  175. set creqw $data(-width)
  176. }
  177. if {$data(-height) != 0} {
  178. set creqh $data(-height)
  179. }
  180. if {$mreqw != $creqw || $mreqh != $creqh } {
  181. if {![info exists data(counter)]} {
  182. set data(counter) 0
  183. }
  184. if {$data(counter) < 50} {
  185. incr data(counter)
  186. tixGeometryRequest $w $creqw $creqh
  187. tixWidgetDoWhenIdle tixScrolledWidget:Repack $w
  188. set data(repack) 1
  189. return
  190. }
  191. }
  192. set data(counter) 0
  193. set mw [winfo width $w]
  194. set mh [winfo height $w]
  195. set cw [expr $mw - $scbW]
  196. set ch [expr $mh - $scbH]
  197. set scbx [expr $mw - $scbW]
  198. set scby [expr $mh - $scbH]
  199. # Check the validity of the sizes: if window was not mapped then
  200. # sizes will be below 1x1
  201. if {$cw < 1} {
  202. set cw 1
  203. }
  204. if {$ch < 1} {
  205. set ch 1
  206. }
  207. if {$scbx < 1} {
  208. set scbx 1
  209. }
  210. if {$scby < 1} {
  211. set scby 1
  212. }
  213. if {[lindex $data(-scrollbar) 0] == "auto"} {
  214. # Find out how we are going to pack the scrollbars
  215. #
  216. set spec [tixScrolledWidget:CheckScrollbars $w $scbW $scbH]
  217. foreach xspec [lrange $data(-scrollbar) 1 end] {
  218. case $xspec {
  219. +x {
  220. set spec [expr $spec | 10]
  221. }
  222. -x {
  223. set spec [expr $spec & 01]
  224. }
  225. +y {
  226. set spec [expr $spec | 01]
  227. }
  228. -y {
  229. set spec [expr $spec & 10]
  230. }
  231. }
  232. }
  233. if {$spec == 0} {
  234. set spec 00
  235. }
  236. if {$spec == 1} {
  237. set spec 01
  238. }
  239. } else {
  240. case $data(-scrollbar) in {
  241. none {
  242. set spec 00
  243. }
  244. x {
  245. set spec 10
  246. }
  247. y {
  248. set spec 01
  249. }
  250. both {
  251. set spec 11
  252. }
  253. }
  254. }
  255. if {$data(lastSpec)==$spec && $data(lastMW)==$mw && $data(lastMH)==$mh} {
  256. if {$data(lastScbW) == $scbW && $data(lastScbH) == $scbH} {
  257. tixCallMethod $w PlaceWindow
  258. set data(repack) 0
  259. return
  260. }
  261. }
  262. set vsbH [expr $mh - $data(vsbPadY)]
  263. set hsbW [expr $mw - $data(hsbPadX)]
  264. if {$vsbH < 1} {
  265. set vsbH 1
  266. }
  267. if {$hsbW < 1} {
  268. set hsbW 1
  269. }
  270. case $spec in {
  271. "00" {
  272. tixMoveResizeWindow $client 0 0 $mw $mh
  273. tixMapWindow $client
  274. tixUnmapWindow $data(w:hsb)
  275. tixUnmapWindow $data(w:vsb)
  276. }
  277. "01" {
  278. tixMoveResizeWindow $client 0 0 $cw $mh
  279. tixMoveResizeWindow $data(w:vsb) $scbx $data(vsbPadY) $scbW $vsbH
  280. tixMapWindow $client
  281. tixUnmapWindow $data(w:hsb)
  282. tixMapWindow $data(w:vsb)
  283. }
  284. "10" {
  285. tixMoveResizeWindow $client 0 0 $mw $ch
  286. tixMoveResizeWindow $data(w:hsb) $data(hsbPadX) $scby $hsbW $scbH
  287. tixMapWindow $client
  288. tixMapWindow $data(w:hsb)
  289. tixUnmapWindow $data(w:vsb)
  290. }
  291. "11" {
  292. set vsbH [expr $ch - $data(vsbPadY)]
  293. set hsbW [expr $cw - $data(hsbPadX)]
  294. if {$vsbH < 1} {
  295. set vsbH 1
  296. }
  297. if {$hsbW < 1} {
  298. set hsbW 1
  299. }
  300. tixMoveResizeWindow $client 0 0 $cw $ch
  301. tixMoveResizeWindow $data(w:vsb) $scbx $data(vsbPadY) $scbW $vsbH
  302. tixMoveResizeWindow $data(w:hsb) $data(hsbPadX) $scby $hsbW $scbH
  303. if {$data(-sizebox) && $tcl_platform(platform) == "windows"} {
  304. tixMoveResizeWindow $data(w:sizebox) $scbx $scby $scbW $scbH
  305. }
  306. tixMapWindow $client
  307. tixMapWindow $data(w:hsb)
  308. tixMapWindow $data(w:vsb)
  309. if {$data(-sizebox) && $tcl_platform(platform) == "windows"} {
  310. tixMapWindow $data(w:sizebox)
  311. }
  312. }
  313. }
  314. set data(lastSpec) $spec
  315. set data(lastMW) $mw
  316. set data(lastMH) $mh
  317. set data(lastScbW) $scbW
  318. set data(lastScbH) $scbH
  319. tixCallMethod $w PlaceWindow
  320. set data(repack) 0
  321. }
  322. proc tixScrolledWidget:PlaceWindow {w} {
  323. # virtual base function
  324. }
  325. #
  326. # Helper function
  327. #
  328. proc tixScrolledWidget:NeedScrollbar {w axis} {
  329. upvar #0 $w data
  330. if {$data($axis,first) > 0.0} {
  331. return 1
  332. }
  333. if {$data($axis,last) < 1.0} {
  334. return 1
  335. }
  336. return 0
  337. }
  338. # Return whether H and V needs scrollbars in a list of two booleans
  339. #
  340. #
  341. proc tixScrolledWidget:CheckScrollbars {w scbW scbH} {
  342. upvar #0 $w data
  343. set mW [winfo width $w]
  344. set mH [winfo height $w]
  345. set info [tixCallMethod $w GeometryInfo $mW $mH]
  346. if {$info != ""} {
  347. set xSpec [lindex $info 0]
  348. set ySpec [lindex $info 1]
  349. set data(x,first) [lindex $xSpec 0]
  350. set data(x,last) [lindex $xSpec 1]
  351. set data(y,first) [lindex $ySpec 0]
  352. set data(y,last) [lindex $ySpec 1]
  353. }
  354. set needX [tixScrolledWidget:NeedScrollbar $w x]
  355. set needY [tixScrolledWidget:NeedScrollbar $w y]
  356. if {[winfo ismapped $w]==0} {
  357. return "$needX$needY"
  358. }
  359. if {$needX && $needY} {
  360. return 11
  361. }
  362. if {$needX == 0 && $needY == 0} {
  363. return 00
  364. }
  365. if {$needX} {
  366. set mH [expr $mH - $scbH]
  367. }
  368. if {$needY} {
  369. set mW [expr $mW - $scbW]
  370. }
  371. set info [tixCallMethod $w GeometryInfo $mW $mH]
  372. if {$info != ""} {
  373. set xSpec [lindex $info 0]
  374. set ySpec [lindex $info 1]
  375. set data(x,first) [lindex $xSpec 0]
  376. set data(x,last) [lindex $xSpec 1]
  377. set data(y,first) [lindex $ySpec 0]
  378. set data(y,last) [lindex $ySpec 1]
  379. }
  380. set needX [tixScrolledWidget:NeedScrollbar $w x]
  381. set needY [tixScrolledWidget:NeedScrollbar $w y]
  382. return "$needX$needY"
  383. }