panedw.tcl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 {=0}}
  21. {-weight Int 1 0 {=0}}
  22. }
  23. }
  24. Widget::declare PanedWindow {
  25. {-side Enum top 1 {top left bottom right}}
  26. {-width Int 10 1 {=6 ""}}
  27. {-pad Int 4 1 {=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::getoption $path -background]
  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 -highlightthickness 0 \
  89. -width $width -height $width -bg $bg]
  90. set sep [frame $frame.sep -bd 1 -relief raised -highlightthickness 0 -bg $bg]
  91. set but [frame $frame.but -bd 1 -relief raised -highlightthickness 0 -bg $bg \
  92. -width $wbut -height $wbut]
  93. if { ![string compare $side "top"] || ![string compare $side "bottom"] } {
  94. place $sep -relx 0.5 -y 0 -width 2 -relheight 1.0 -anchor n
  95. if { ![string compare $side "top"] } {
  96. place $but -relx 0.5 -y [expr {6+$wbut/2}] -anchor c
  97. } else {
  98. place $but -relx 0.5 -rely 1.0 -y [expr {-6-$wbut/2}] -anchor c
  99. }
  100. $but configure -cursor sb_h_double_arrow
  101. grid $frame -column [expr 2*$num-1] -row 0 -sticky ns
  102. grid columnconfigure $path [expr 2*$num-1] -weight 0
  103. } else {
  104. place $sep -x 0 -rely 0.5 -height 2 -relwidth 1.0 -anchor w
  105. if { ![string compare $side "left"] } {
  106. place $but -rely 0.5 -x [expr {6+$wbut/2}] -anchor c
  107. } else {
  108. place $but -rely 0.5 -relx 1.0 -x [expr {-6-$wbut/2}] -anchor c
  109. }
  110. $but configure -cursor sb_v_double_arrow
  111. grid $frame -row [expr 2*$num-1] -column 0 -sticky ew
  112. grid rowconfigure $path [expr 2*$num-1] -weight 0
  113. }
  114. bind $but <ButtonPress-1> "PanedWindow::_beg_move_sash $path $num %X %Y"
  115. } else {
  116. if { ![string compare $side "top"] || ![string compare $side "bottom"] } {
  117. grid rowconfigure $path 0 -weight 1
  118. } else {
  119. grid columnconfigure $path 0 -weight 1
  120. }
  121. }
  122. set pane [frame $path.f$num -bd 0 -relief flat -highlightthickness 0 -bg $bg]
  123. set user [frame $path.f$num.frame -bd 0 -relief flat -highlightthickness 0 -bg $bg]
  124. if { ![string compare $side "top"] || ![string compare $side "bottom"] } {
  125. grid $pane -column [expr 2*$num] -row 0 -sticky nsew
  126. grid columnconfigure $path [expr 2*$num] \
  127. -weight [Widget::getoption $path.f$num -weight]
  128. } else {
  129. grid $pane -row [expr 2*$num] -column 0 -sticky nsew
  130. grid rowconfigure $path [expr 2*$num] \
  131. -weight [Widget::getoption $path.f$num -weight]
  132. }
  133. pack $user -fill both -expand yes
  134. incr _panedw($path,nbpanes)
  135. return $user
  136. }
  137. # ------------------------------------------------------------------------------
  138. # Command PanedWindow::getframe
  139. # ------------------------------------------------------------------------------
  140. proc PanedWindow::getframe { path index } {
  141. if { [winfo exists $path.f$index.frame] } {
  142. return $path.f$index.frame
  143. }
  144. }
  145. # ------------------------------------------------------------------------------
  146. # Command PanedWindow::_destroy
  147. # ------------------------------------------------------------------------------
  148. proc PanedWindow::_destroy { path } {
  149. variable _panedw
  150. for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} {
  151. Widget::destroy $path.f$i
  152. }
  153. unset _panedw($path,nbpanes)
  154. Widget::destroy $path
  155. rename $path {}
  156. }
  157. # ------------------------------------------------------------------------------
  158. # Command PanedWindow::_beg_move_sash
  159. # ------------------------------------------------------------------------------
  160. proc PanedWindow::_beg_move_sash { path num x y } {
  161. variable _panedw
  162. set fprev $path.f[expr $num-1]
  163. set fnext $path.f$num
  164. set wsash [expr [Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]]
  165. $path.sash$num.but configure -relief sunken
  166. set top [toplevel $path.sash -borderwidth 1 -relief raised]
  167. set minszg [Widget::getoption $fprev -minsize]
  168. set minszd [Widget::getoption $fnext -minsize]
  169. set side [Widget::getoption $path -side]
  170. if { ![string compare $side "top"] || ![string compare $side "bottom"] } {
  171. $top configure -cursor sb_h_double_arrow
  172. set h [winfo height $path]
  173. set yr [winfo rooty $path.sash$num]
  174. set xmin [expr $wsash/2+[winfo rootx $fprev]+$minszg]
  175. set xmax [expr -$wsash/2-1+[winfo rootx $fnext]+[winfo width $fnext]-$minszd]
  176. wm overrideredirect $top 1
  177. wm geom $top "2x${h}+$x+$yr"
  178. update idletasks
  179. grab set $top
  180. bind $top <ButtonRelease-1> "PanedWindow::_end_move_sash $path $top $num $xmin $xmax %X rootx width"
  181. bind $top <Motion> "PanedWindow::_move_sash $top $xmin $xmax %X +%%d+$yr"
  182. _move_sash $top $xmin $xmax $x "+%d+$yr"
  183. } else {
  184. $top configure -cursor sb_v_double_arrow
  185. set w [winfo width $path]
  186. set xr [winfo rootx $path.sash$num]
  187. set ymin [expr $wsash/2+[winfo rooty $fprev]+$minszg]
  188. set ymax [expr -$wsash/2-1+[winfo rooty $fnext]+[winfo height $fnext]-$minszd]
  189. wm overrideredirect $top 1
  190. wm geom $top "${w}x2+$xr+$y"
  191. update idletasks
  192. grab set $top
  193. bind $top <ButtonRelease-1> "PanedWindow::_end_move_sash $path $top $num $ymin $ymax %Y rooty height"
  194. bind $top <Motion> "PanedWindow::_move_sash $top $ymin $ymax %Y +$xr+%%d"
  195. _move_sash $top $ymin $ymax $y "+$xr+%d"
  196. }
  197. }
  198. # ------------------------------------------------------------------------------
  199. # Command PanedWindow::_move_sash
  200. # ------------------------------------------------------------------------------
  201. proc PanedWindow::_move_sash { top min max v form } {
  202. if { $v < $min } {
  203. set v $min
  204. } elseif { $v > $max } {
  205. set v $max
  206. }
  207. wm geom $top [format $form $v]
  208. }
  209. # ------------------------------------------------------------------------------
  210. # Command PanedWindow::_end_move_sash
  211. # ------------------------------------------------------------------------------
  212. proc PanedWindow::_end_move_sash { path top num min max v rootv size } {
  213. variable _panedw
  214. destroy $top
  215. if { $v < $min } {
  216. set v $min
  217. } elseif { $v > $max } {
  218. set v $max
  219. }
  220. set fprev $path.f[expr $num-1]
  221. set fnext $path.f$num
  222. $path.sash$num.but configure -relief raised
  223. set wsash [expr [Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]]
  224. set dv [expr $v-[winfo $rootv $path.sash$num]-$wsash/2]
  225. set w1 [winfo $size $fprev]
  226. set w2 [winfo $size $fnext]
  227. for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} {
  228. if { $i == $num-1} {
  229. $fprev configure -$size [expr [winfo $size $fprev]+$dv]
  230. } elseif { $i == $num } {
  231. $fnext configure -$size [expr [winfo $size $fnext]-$dv]
  232. } else {
  233. $path.f$i configure -$size [winfo $size $path.f$i]
  234. }
  235. }
  236. }
  237. # ------------------------------------------------------------------------------
  238. # Command PanedWindow::_realize
  239. # ------------------------------------------------------------------------------
  240. proc PanedWindow::_realize { path width height } {
  241. variable _panedw
  242. set x 0
  243. set y 0
  244. set hc [winfo reqheight $path]
  245. set hmax 0
  246. for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} {
  247. $path.f$i configure \
  248. -width [winfo reqwidth $path.f$i.frame] \
  249. -height [winfo reqheight $path.f$i.frame]
  250. place $path.f$i.frame -x 0 -y 0 -relwidth 1 -relheight 1
  251. }
  252. bind $path <Configure> {}
  253. }