VStack.tcl 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
  2. #
  3. # $Id: VStack.tcl,v 1.4 2004/03/28 02:44:57 hobbs Exp $
  4. #
  5. # VStack.tcl --
  6. #
  7. # Virtual base class, do not instantiate! This is the core
  8. # class for all NoteBook style widgets. Stack maintains a list
  9. # of windows. It provides methods to create, delete windows as
  10. # well as stepping through them.
  11. #
  12. # Copyright (c) 1993-1999 Ioi Kim Lam.
  13. # Copyright (c) 2000-2001 Tix Project Group.
  14. #
  15. # See the file "license.terms" for information on usage and redistribution
  16. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  17. #
  18. #
  19. tixWidgetClass tixVStack {
  20. -virtual true
  21. -classname TixVStack
  22. -superclass tixPrimitive
  23. -method {
  24. add delete pageconfigure pagecget pages raise raised
  25. }
  26. -flag {
  27. -dynamicgeometry -ipadx -ipady
  28. }
  29. -configspec {
  30. {-dynamicgeometry dynamicGeometry DynamicGeometry 0 tixVerifyBoolean}
  31. {-ipadx ipadX Pad 0}
  32. {-ipady ipadY Pad 0}
  33. }
  34. }
  35. proc tixVStack:InitWidgetRec {w} {
  36. upvar #0 $w data
  37. tixChainMethod $w InitWidgetRec
  38. set data(pad-x1) 0
  39. set data(pad-x2) 0
  40. set data(pad-y1) 0
  41. set data(pad-y2) 0
  42. set data(windows) ""
  43. set data(nWindows) 0
  44. set data(topchild) ""
  45. set data(minW) 1
  46. set data(minH) 1
  47. set data(w:top) $w
  48. set data(counter) 0
  49. set data(repack) 0
  50. }
  51. proc tixVStack:SetBindings {w} {
  52. upvar #0 $w data
  53. tixChainMethod $w SetBindings
  54. tixCallMethod $w InitGeometryManager
  55. }
  56. #----------------------------------------------------------------------
  57. # Public methods
  58. #----------------------------------------------------------------------
  59. proc tixVStack:add {w child args} {
  60. upvar #0 $w data
  61. set validOptions {-createcmd -raisecmd}
  62. set opt(-createcmd) ""
  63. set opt(-raisecmd) ""
  64. tixHandleOptions -nounknown opt $validOptions $args
  65. set data($child,raisecmd) $opt(-raisecmd)
  66. set data($child,createcmd) $opt(-createcmd)
  67. set data(w:$child) [tixCallMethod $w CreateChildFrame $child]
  68. lappend data(windows) $child
  69. incr data(nWindows) 1
  70. return $data(w:$child)
  71. }
  72. proc tixVStack:delete {w child} {
  73. upvar #0 $w data
  74. if {[info exists data($child,createcmd)]} {
  75. if {[winfo exists $data(w:$child)]} {
  76. bind $data(w:$child) <Destroy> {;}
  77. destroy $data(w:$child)
  78. }
  79. catch {unset data($child,createcmd)}
  80. catch {unset data($child,raisecmd)}
  81. catch {unset data(w:$child)}
  82. set index [lsearch $data(windows) $child]
  83. if {$index >= 0} {
  84. set data(windows) [lreplace $data(windows) $index $index]
  85. incr data(nWindows) -1
  86. }
  87. if {[string equal $data(topchild) $child]} {
  88. set data(topchild) ""
  89. foreach page $data(windows) {
  90. if {$page ne $child} {
  91. $w raise $page
  92. set data(topchild) $page
  93. break
  94. }
  95. }
  96. }
  97. } else {
  98. error "page $child does not exist"
  99. }
  100. }
  101. proc tixVStack:pagecget {w child option} {
  102. upvar #0 $w data
  103. if {![info exists data($child,createcmd)]} {
  104. error "page \"$child\" does not exist in $w"
  105. }
  106. case $option {
  107. -createcmd {
  108. return "$data($child,createcmd)"
  109. }
  110. -raisecmd {
  111. return "$data($child,raisecmd)"
  112. }
  113. default {
  114. if {$data(w:top) ne $w} {
  115. return [$data(w:top) pagecget $child $option]
  116. } else {
  117. error "unknown option \"$option\""
  118. }
  119. }
  120. }
  121. }
  122. proc tixVStack:pageconfigure {w child args} {
  123. upvar #0 $w data
  124. if {![info exists data($child,createcmd)]} {
  125. error "page \"$child\" does not exist in $w"
  126. }
  127. set len [llength $args]
  128. if {$len == 0} {
  129. set value [$data(w:top) pageconfigure $child]
  130. lappend value [list -createcmd "" "" "" $data($child,createcmd)]
  131. lappend value [list -raisecmd "" "" "" $data($child,raisecmd)]
  132. return $value
  133. }
  134. if {$len == 1} {
  135. case [lindex $args 0] {
  136. -createcmd {
  137. return [list -createcmd "" "" "" $data($child,createcmd)]
  138. }
  139. -raisecmd {
  140. return [list -raisecmd "" "" "" $data($child,raisecmd)]
  141. }
  142. default {
  143. return [$data(w:top) pageconfigure $child [lindex $args 0]]
  144. }
  145. }
  146. }
  147. # By default handle each of the options
  148. #
  149. set opt(-createcmd) $data($child,createcmd)
  150. set opt(-raisecmd) $data($child,raisecmd)
  151. tixHandleOptions -nounknown opt {-createcmd -raisecmd} $args
  152. #
  153. # the widget options
  154. set new_args ""
  155. foreach {flag value} $args {
  156. if {$flag ne "-createcmd" && $flag ne "-raisecmd"} {
  157. lappend new_args $flag
  158. lappend new_args $value
  159. }
  160. }
  161. if {[llength $new_args] >= 2} {
  162. eval $data(w:top) pageconfig $child $new_args
  163. }
  164. #
  165. # The add-on options
  166. set data($child,raisecmd) $opt(-raisecmd)
  167. set data($child,createcmd) $opt(-createcmd)
  168. return ""
  169. }
  170. proc tixVStack:pages {w} {
  171. upvar #0 $w data
  172. return $data(windows)
  173. }
  174. proc tixVStack:raise {w child} {
  175. upvar #0 $w data
  176. if {![info exists data($child,createcmd)]} {
  177. error "page $child does not exist"
  178. }
  179. if {[llength $data($child,createcmd)]} {
  180. uplevel #0 $data($child,createcmd)
  181. set data($child,createcmd) ""
  182. }
  183. tixCallMethod $w RaiseChildFrame $child
  184. set oldTopChild $data(topchild)
  185. set data(topchild) $child
  186. if {$oldTopChild ne $child} {
  187. if {[llength $data($child,raisecmd)]} {
  188. uplevel #0 $data($child,raisecmd)
  189. }
  190. }
  191. }
  192. proc tixVStack:raised {w} {
  193. upvar #0 $w data
  194. return $data(topchild)
  195. }
  196. #----------------------------------------------------------------------
  197. # Virtual Methods
  198. #----------------------------------------------------------------------
  199. proc tixVStack:InitGeometryManager {w} {
  200. upvar #0 $w data
  201. bind $w <Configure> "tixVStack:MasterGeomProc $w"
  202. bind $data(w:top) <Destroy> "+tixVStack:DestroyTop $w"
  203. if {$data(repack) == 0} {
  204. set data(repack) 1
  205. tixWidgetDoWhenIdle tixCallMethod $w Resize
  206. }
  207. }
  208. proc tixVStack:CreateChildFrame {w child} {
  209. upvar #0 $w data
  210. set f [frame $data(w:top).$child]
  211. tixManageGeometry $f "tixVStack:ClientGeomProc $w"
  212. bind $f <Configure> "tixVStack:ClientGeomProc $w -configure $f"
  213. bind $f <Destroy> "$w delete $child"
  214. return $f
  215. }
  216. proc tixVStack:RaiseChildFrame {w child} {
  217. upvar #0 $w data
  218. # Hide the original visible window
  219. if {$data(topchild) ne "" && $data(topchild) ne $child} {
  220. tixUnmapWindow $data(w:$data(topchild))
  221. }
  222. set myW [winfo width $w]
  223. set myH [winfo height $w]
  224. set cW [expr {$myW - $data(pad-x1) - $data(pad-x2) - 2*$data(-ipadx)}]
  225. set cH [expr {$myH - $data(pad-y1) - $data(pad-y2) - 2*$data(-ipady)}]
  226. set cX [expr {$data(pad-x1) + $data(-ipadx)}]
  227. set cY [expr {$data(pad-y1) + $data(-ipady)}]
  228. if {$cW > 0 && $cH > 0} {
  229. tixMoveResizeWindow $data(w:$child) $cX $cY $cW $cH
  230. tixMapWindow $data(w:$child)
  231. raise $data(w:$child)
  232. }
  233. }
  234. #----------------------------------------------------------------------
  235. #
  236. # G E O M E T R Y M A N A G E M E N T
  237. #
  238. #----------------------------------------------------------------------
  239. proc tixVStack:DestroyTop {w} {
  240. catch {
  241. destroy $w
  242. }
  243. }
  244. proc tixVStack:MasterGeomProc {w args} {
  245. if {![winfo exists $w]} {
  246. return
  247. }
  248. upvar #0 $w data
  249. if {$data(repack) == 0} {
  250. set data(repack) 1
  251. tixWidgetDoWhenIdle tixCallMethod $w Resize
  252. }
  253. }
  254. proc tixVStack:ClientGeomProc {w flag client} {
  255. if {![winfo exists $w]} {
  256. return
  257. }
  258. upvar #0 $w data
  259. if {$data(repack) == 0} {
  260. set data(repack) 1
  261. tixWidgetDoWhenIdle tixCallMethod $w Resize
  262. }
  263. if {$flag eq "-lostslave"} {
  264. error "Geometry Management Error: \
  265. Another geometry manager has taken control of $client.\
  266. This error is usually caused because a widget has been created\
  267. in the wrong frame: it should have been created inside $client instead\
  268. of $w"
  269. }
  270. }
  271. proc tixVStack:Resize {w} {
  272. if {![winfo exists $w]} {
  273. return
  274. }
  275. upvar #0 $w data
  276. if {$data(nWindows) == 0} {
  277. set data(repack) 0
  278. return
  279. }
  280. if {$data(-width) == 0 || $data(-height) == 0} {
  281. if {!$data(-dynamicgeometry)} {
  282. # Calculate my required width and height
  283. #
  284. set maxW 1
  285. set maxH 1
  286. foreach child $data(windows) {
  287. set cW [winfo reqwidth $data(w:$child)]
  288. set cH [winfo reqheight $data(w:$child)]
  289. if {$maxW < $cW} {
  290. set maxW $cW
  291. }
  292. if {$maxH < $cH} {
  293. set maxH $cH
  294. }
  295. }
  296. set reqW $maxW
  297. set reqH $maxH
  298. } else {
  299. if {$data(topchild) ne ""} {
  300. set reqW [winfo reqwidth $data(w:$data(topchild))]
  301. set reqH [winfo reqheight $data(w:$data(topchild))]
  302. } else {
  303. set reqW 1
  304. set reqH 1
  305. }
  306. }
  307. incr reqW [expr {$data(pad-x1) + $data(pad-x2) + 2*$data(-ipadx)}]
  308. incr reqH [expr {$data(pad-y1) + $data(pad-y2) + 2*$data(-ipady)}]
  309. if {$reqW < $data(minW)} {
  310. set reqW $data(minW)
  311. }
  312. if {$reqH < $data(minH)} {
  313. set reqH $data(minH)
  314. }
  315. }
  316. # These take higher precedence
  317. #
  318. if {$data(-width) != 0} {
  319. set reqW $data(-width)
  320. }
  321. if {$data(-height) != 0} {
  322. set reqH $data(-height)
  323. }
  324. if {[winfo reqwidth $w] != $reqW || [winfo reqheight $w] != $reqH} {
  325. if {![info exists data(counter)]} {
  326. set data(counter) 0
  327. }
  328. if {$data(counter) < 50} {
  329. incr data(counter)
  330. tixGeometryRequest $w $reqW $reqH
  331. tixWidgetDoWhenIdle tixCallMethod $w Resize
  332. set data(repack) 1
  333. return
  334. }
  335. }
  336. set data(counter) 0
  337. if {$data(w:top) ne $w} {
  338. tixMoveResizeWindow $data(w:top) 0 0 [winfo width $w] [winfo height $w]
  339. tixMapWindow $data(w:top)
  340. }
  341. if {[string equal $data(topchild) ""]} {
  342. set top [lindex $data(windows) 0]
  343. } else {
  344. set top $data(topchild)
  345. }
  346. if {$top ne ""} {
  347. tixCallMethod $w raise $top
  348. }
  349. set data(repack) 0
  350. }