PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/bwidget/panedw.tcl

https://gitlab.com/OpenSourceMirror/vtcl
TCL | 325 lines | 229 code | 50 blank | 46 comment | 36 complexity | cd5b422b86a16f11d072f7058d1baa8c MD5 | raw file
  1. # ------------------------------------------------------------------------------
  2. # panedw.tcl
  3. # This file is part of Unifix BWidget Toolkit
  4. # ------------------------------------------------------------------------------
  5. # Index of commands:
  6. # - PanedWindow::create
  7. # - PanedWindow::configure
  8. # - PanedWindow::cget
  9. # - PanedWindow::add
  10. # - PanedWindow::getframe
  11. # - PanedWindow::_destroy
  12. # - PanedWindow::_beg_move_sash
  13. # - PanedWindow::_move_sash
  14. # - PanedWindow::_end_move_sash
  15. # - PanedWindow::_realize
  16. # ------------------------------------------------------------------------------
  17. namespace eval PanedWindow {
  18. namespace eval Pane {
  19. Widget::declare PanedWindow::Pane {
  20. {-minsize Int 0 0 "%d >= 0"}
  21. {-weight Int 1 0 "%d >= 0"}
  22. }
  23. }
  24. Widget::declare PanedWindow {
  25. {-side Enum top 1 {top left bottom right}}
  26. {-width Int 10 1 "%d >=6"}
  27. {-pad Int 4 1 "%d >= 0"}
  28. {-background TkResource "" 0 frame}
  29. {-bg Synonym -background}
  30. }
  31. variable _panedw
  32. proc ::PanedWindow { path args } { return [eval PanedWindow::create $path $args] }
  33. proc use {} {}
  34. }
  35. # ------------------------------------------------------------------------------
  36. # Command PanedWindow::create
  37. # ------------------------------------------------------------------------------
  38. proc PanedWindow::create { path args } {
  39. variable _panedw
  40. Widget::init PanedWindow $path $args
  41. frame $path -background [Widget::cget $path -background] -class PanedWindow
  42. set _panedw($path,nbpanes) 0
  43. bind $path <Configure> "PanedWindow::_realize $path %w %h"
  44. bind $path <Destroy> "PanedWindow::_destroy $path"
  45. rename $path ::$path:cmd
  46. proc ::$path { cmd args } "return \[eval PanedWindow::\$cmd $path \$args\]"
  47. return $path
  48. }
  49. # ------------------------------------------------------------------------------
  50. # Command PanedWindow::configure
  51. # ------------------------------------------------------------------------------
  52. proc PanedWindow::configure { path args } {
  53. variable _panedw
  54. set res [Widget::configure $path $args]
  55. if { [Widget::hasChanged $path -background bg] && $_panedw($path,nbpanes) > 0 } {
  56. $path:cmd configure -background $bg
  57. $path.f0 configure -background $bg
  58. for {set i 1} {$i < $_panedw($path,nbpanes)} {incr i} {
  59. set frame $path.sash$i
  60. $frame configure -background $bg
  61. $frame.sep configure -background $bg
  62. $frame.but configure -background $bg
  63. $path.f$i configure -background $bg
  64. $path.f$i.frame configure -background $bg
  65. }
  66. }
  67. return $res
  68. }
  69. # ------------------------------------------------------------------------------
  70. # Command PanedWindow::cget
  71. # ------------------------------------------------------------------------------
  72. proc PanedWindow::cget { path option } {
  73. return [Widget::cget $path $option]
  74. }
  75. # ------------------------------------------------------------------------------
  76. # Command PanedWindow::add
  77. # ------------------------------------------------------------------------------
  78. proc PanedWindow::add { path args } {
  79. variable _panedw
  80. set num $_panedw($path,nbpanes)
  81. Widget::init PanedWindow::Pane $path.f$num $args
  82. set bg [Widget::getoption $path -background]
  83. set wbut [Widget::getoption $path -width]
  84. set pad [Widget::getoption $path -pad]
  85. set width [expr {$wbut+2*$pad}]
  86. set side [Widget::getoption $path -side]
  87. if { $num > 0 } {
  88. set frame [frame $path.sash$num -relief flat -bd 0 \
  89. -highlightthickness 0 -width $width -height $width -bg $bg]
  90. set sep [frame $frame.sep -bd 5 -relief raised \
  91. -highlightthickness 0 -bg $bg]
  92. set but [frame $frame.but -bd 1 -relief raised \
  93. -highlightthickness 0 -bg $bg -width $wbut -height $wbut]
  94. set placeButton 1
  95. set sepsize 2
  96. if { $::tcl_platform(platform) != "windows" } {
  97. set activator $but
  98. } else {
  99. set activator $sep
  100. set sepsize 4
  101. $sep configure -bd 3
  102. set placeButton 0
  103. }
  104. if { ![string compare $side "top"] || \
  105. ![string compare $side "bottom"] } {
  106. place $sep -relx 0.5 -y 0 -width $sepsize -relheight 1.0 -anchor n
  107. if { $placeButton } {
  108. if { ![string compare $side "top"] } {
  109. place $but -relx 0.5 -y [expr {6+$wbut/2}] -anchor c
  110. } else {
  111. place $but -relx 0.5 -rely 1.0 -y [expr {-6-$wbut/2}] \
  112. -anchor c
  113. }
  114. }
  115. $activator configure -cursor sb_h_double_arrow
  116. grid $frame -column [expr {2*$num-1}] -row 0 -sticky ns
  117. grid columnconfigure $path [expr {2*$num-1}] -weight 0
  118. } else {
  119. place $sep -x 0 -rely 0.5 -height $sepsize -relwidth 1.0 -anchor w
  120. if { $placeButton } {
  121. if { ![string compare $side "left"] } {
  122. place $but -rely 0.5 -x [expr {6+$wbut/2}] -anchor c
  123. } else {
  124. place $but -rely 0.5 -relx 1.0 -x [expr {-6-$wbut/2}] \
  125. -anchor c
  126. }
  127. }
  128. $activator configure -cursor sb_v_double_arrow
  129. grid $frame -row [expr {2*$num-1}] -column 0 -sticky ew
  130. grid rowconfigure $path [expr {2*$num-1}] -weight 0
  131. }
  132. bind $activator <ButtonPress-1> \
  133. "PanedWindow::_beg_move_sash $path $num %X %Y"
  134. } else {
  135. if { ![string compare $side "top"] || \
  136. ![string compare $side "bottom"] } {
  137. grid rowconfigure $path 0 -weight 1
  138. } else {
  139. grid columnconfigure $path 0 -weight 1
  140. }
  141. }
  142. set pane [frame $path.f$num -bd 0 -relief flat \
  143. -highlightthickness 0 -bg $bg]
  144. set user [frame $path.f$num.frame -bd 0 -relief flat \
  145. -highlightthickness 0 -bg $bg]
  146. if { ![string compare $side "top"] || ![string compare $side "bottom"] } {
  147. grid $pane -column [expr {2*$num}] -row 0 -sticky nsew
  148. grid columnconfigure $path [expr {2*$num}] \
  149. -weight [Widget::getoption $path.f$num -weight]
  150. } else {
  151. grid $pane -row [expr {2*$num}] -column 0 -sticky nsew
  152. grid rowconfigure $path [expr {2*$num}] \
  153. -weight [Widget::getoption $path.f$num -weight]
  154. }
  155. pack $user -fill both -expand yes
  156. incr _panedw($path,nbpanes)
  157. return $user
  158. }
  159. # ------------------------------------------------------------------------------
  160. # Command PanedWindow::getframe
  161. # ------------------------------------------------------------------------------
  162. proc PanedWindow::getframe { path index } {
  163. if { [winfo exists $path.f$index.frame] } {
  164. return $path.f$index.frame
  165. }
  166. }
  167. # ------------------------------------------------------------------------------
  168. # Command PanedWindow::_destroy
  169. # ------------------------------------------------------------------------------
  170. proc PanedWindow::_destroy { path } {
  171. variable _panedw
  172. for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} {
  173. Widget::destroy $path.f$i
  174. }
  175. unset _panedw($path,nbpanes)
  176. Widget::destroy $path
  177. rename $path {}
  178. }
  179. # ------------------------------------------------------------------------------
  180. # Command PanedWindow::_beg_move_sash
  181. # ------------------------------------------------------------------------------
  182. proc PanedWindow::_beg_move_sash { path num x y } {
  183. variable _panedw
  184. set fprev $path.f[expr {$num-1}]
  185. set fnext $path.f$num
  186. set wsash [expr {[Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]}]
  187. $path.sash$num.but configure -relief sunken
  188. set top [toplevel $path.sash -borderwidth 1 -relief raised]
  189. set minszg [Widget::getoption $fprev -minsize]
  190. set minszd [Widget::getoption $fnext -minsize]
  191. set side [Widget::getoption $path -side]
  192. if { ![string compare $side "top"] || ![string compare $side "bottom"] } {
  193. $top configure -cursor sb_h_double_arrow
  194. set h [winfo height $path]
  195. set yr [winfo rooty $path.sash$num]
  196. set xmin [expr {$wsash/2+[winfo rootx $fprev]+$minszg}]
  197. set xmax [expr {-$wsash/2-1+[winfo rootx $fnext]+[winfo width $fnext]-$minszd}]
  198. wm overrideredirect $top 1
  199. wm geom $top "2x${h}+$x+$yr"
  200. update idletasks
  201. grab set $top
  202. bind $top <ButtonRelease-1> "PanedWindow::_end_move_sash $path $top $num $xmin $xmax %X rootx width"
  203. bind $top <Motion> "PanedWindow::_move_sash $top $xmin $xmax %X +%%d+$yr"
  204. _move_sash $top $xmin $xmax $x "+%d+$yr"
  205. } else {
  206. $top configure -cursor sb_v_double_arrow
  207. set w [winfo width $path]
  208. set xr [winfo rootx $path.sash$num]
  209. set ymin [expr {$wsash/2+[winfo rooty $fprev]+$minszg}]
  210. set ymax [expr {-$wsash/2-1+[winfo rooty $fnext]+[winfo height $fnext]-$minszd}]
  211. wm overrideredirect $top 1
  212. wm geom $top "${w}x2+$xr+$y"
  213. update idletasks
  214. grab set $top
  215. bind $top <ButtonRelease-1> "PanedWindow::_end_move_sash $path $top $num $ymin $ymax %Y rooty height"
  216. bind $top <Motion> "PanedWindow::_move_sash $top $ymin $ymax %Y +$xr+%%d"
  217. _move_sash $top $ymin $ymax $y "+$xr+%d"
  218. }
  219. }
  220. # ------------------------------------------------------------------------------
  221. # Command PanedWindow::_move_sash
  222. # ------------------------------------------------------------------------------
  223. proc PanedWindow::_move_sash { top min max v form } {
  224. if { $v < $min } {
  225. set v $min
  226. } elseif { $v > $max } {
  227. set v $max
  228. }
  229. wm geom $top [format $form $v]
  230. }
  231. # ------------------------------------------------------------------------------
  232. # Command PanedWindow::_end_move_sash
  233. # ------------------------------------------------------------------------------
  234. proc PanedWindow::_end_move_sash { path top num min max v rootv size } {
  235. variable _panedw
  236. destroy $top
  237. if { $v < $min } {
  238. set v $min
  239. } elseif { $v > $max } {
  240. set v $max
  241. }
  242. set fprev $path.f[expr {$num-1}]
  243. set fnext $path.f$num
  244. $path.sash$num.but configure -relief raised
  245. set wsash [expr {[Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]}]
  246. set dv [expr {$v-[winfo $rootv $path.sash$num]-$wsash/2}]
  247. set w1 [winfo $size $fprev]
  248. set w2 [winfo $size $fnext]
  249. for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} {
  250. if { $i == $num-1} {
  251. $fprev configure -$size [expr {[winfo $size $fprev]+$dv}]
  252. } elseif { $i == $num } {
  253. $fnext configure -$size [expr {[winfo $size $fnext]-$dv}]
  254. } else {
  255. $path.f$i configure -$size [winfo $size $path.f$i]
  256. }
  257. }
  258. }
  259. # ------------------------------------------------------------------------------
  260. # Command PanedWindow::_realize
  261. # ------------------------------------------------------------------------------
  262. proc PanedWindow::_realize { path width height } {
  263. variable _panedw
  264. set x 0
  265. set y 0
  266. set hc [winfo reqheight $path]
  267. set hmax 0
  268. for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} {
  269. $path.f$i configure \
  270. -width [winfo reqwidth $path.f$i.frame] \
  271. -height [winfo reqheight $path.f$i.frame]
  272. place $path.f$i.frame -x 0 -y 0 -relwidth 1 -relheight 1
  273. }
  274. bind $path <Configure> {}
  275. }