scrollframe.tcl 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. # ------------------------------------------------------------------------------
  2. # scrollframe.tcl
  3. # This file is part of Unifix BWidget Toolkit
  4. # $Id$
  5. # ------------------------------------------------------------------------------
  6. # Index of commands:
  7. # - ScrollableFrame::create
  8. # - ScrollableFrame::configure
  9. # - ScrollableFrame::cget
  10. # - ScrollableFrame::getframe
  11. # - ScrollableFrame::see
  12. # - ScrollableFrame::xview
  13. # - ScrollableFrame::yview
  14. # - ScrollableFrame::_resize
  15. # ------------------------------------------------------------------------------
  16. namespace eval ScrollableFrame {
  17. Widget::declare ScrollableFrame {
  18. {-background TkResource "" 0 frame}
  19. {-width Int 0 0 {}}
  20. {-height Int 0 0 {}}
  21. {-areawidth Int 0 0 {}}
  22. {-areaheight Int 0 0 {}}
  23. {-constrainedwidth Boolean 0 0}
  24. {-constrainedheight Boolean 0 0}
  25. {-xscrollcommand TkResource "" 0 canvas}
  26. {-yscrollcommand TkResource "" 0 canvas}
  27. {-xscrollincrement TkResource "" 0 canvas}
  28. {-yscrollincrement TkResource "" 0 canvas}
  29. {-bg Synonym -background}
  30. }
  31. Widget::addmap ScrollableFrame "" :cmd {
  32. -background {} -width {} -height {}
  33. -xscrollcommand {} -yscrollcommand {}
  34. -xscrollincrement {} -yscrollincrement {}
  35. }
  36. Widget::addmap ScrollableFrame "" .frame {-background {}}
  37. variable _widget
  38. bind BwScrollableFrame <Configure> {ScrollableFrame::_resize %W}
  39. bind BwScrollableFrame <Destroy> {Widget::destroy %W; rename %W {}}
  40. proc ::ScrollableFrame { path args } { return [eval ScrollableFrame::create $path $args] }
  41. proc use {} {}
  42. }
  43. # ------------------------------------------------------------------------------
  44. # Command ScrollableFrame::create
  45. # ------------------------------------------------------------------------------
  46. proc ScrollableFrame::create { path args } {
  47. Widget::init ScrollableFrame $path $args
  48. set canvas [eval canvas $path [Widget::subcget $path :cmd] \
  49. -highlightthickness 0 -borderwidth 0 -relief flat]
  50. set frame [eval frame $path.frame [Widget::subcget $path .frame] \
  51. -highlightthickness 0 -borderwidth 0 -relief flat]
  52. $canvas create window 0 0 -anchor nw -window $frame -tags win \
  53. -width [Widget::cget $path -areawidth] \
  54. -height [Widget::cget $path -areaheight]
  55. bind $frame <Configure> "$canvas:cmd configure -scrollregion {0 0 %w %h}"
  56. bindtags $path [list $path BwScrollableFrame [winfo toplevel $path] all]
  57. rename $path ::$path:cmd
  58. proc ::$path { cmd args } "return \[eval ScrollableFrame::\$cmd $path \$args\]"
  59. return $canvas
  60. }
  61. # ------------------------------------------------------------------------------
  62. # Command ScrollableFrame::configure
  63. # ------------------------------------------------------------------------------
  64. proc ScrollableFrame::configure { path args } {
  65. set res [Widget::configure $path $args]
  66. set upd 0
  67. set modcw [Widget::hasChanged $path -constrainedwidth cw]
  68. set modw [Widget::hasChanged $path -areawidth w]
  69. if { $modcw || (!$cw && $modw) } {
  70. if { $cw } {
  71. set w [winfo width $path]
  72. }
  73. set upd 1
  74. }
  75. set modch [Widget::hasChanged $path -constrainedheight ch]
  76. set modh [Widget::hasChanged $path -areaheight h]
  77. if { $modch || (!$ch && $modh) } {
  78. if { $ch } {
  79. set h [winfo height $path]
  80. }
  81. set upd 1
  82. }
  83. if { $upd } {
  84. $path:cmd itemconfigure win -width $w -height $h
  85. }
  86. return $res
  87. }
  88. # ------------------------------------------------------------------------------
  89. # Command ScrollableFrame::cget
  90. # ------------------------------------------------------------------------------
  91. proc ScrollableFrame::cget { path option } {
  92. return [Widget::cget $path $option]
  93. }
  94. # ------------------------------------------------------------------------------
  95. # Command ScrollableFrame::getframe
  96. # ------------------------------------------------------------------------------
  97. proc ScrollableFrame::getframe { path } {
  98. return $path.frame
  99. }
  100. # ------------------------------------------------------------------------------
  101. # Command ScrollableFrame::see
  102. # ------------------------------------------------------------------------------
  103. proc ScrollableFrame::see { path widget {vert top} {horz left}} {
  104. set x0 [winfo x $widget]
  105. set y0 [winfo y $widget]
  106. set x1 [expr {$x0+[winfo width $widget]}]
  107. set y1 [expr {$y0+[winfo height $widget]}]
  108. set xb0 [$path:cmd canvasx 0]
  109. set yb0 [$path:cmd canvasy 0]
  110. set xb1 [$path:cmd canvasx [winfo width $path]]
  111. set yb1 [$path:cmd canvasy [winfo height $path]]
  112. set dx 0
  113. set dy 0
  114. if { ![string compare $horz "left"] } {
  115. if { $x1 > $xb1 } {
  116. set dx [expr {$x1-$xb1}]
  117. }
  118. if { $x0 < $xb0+$dx } {
  119. set dx [expr {$x0-$xb0}]
  120. }
  121. } elseif { ![string compare $horz "right"] } {
  122. if { $x0 < $xb0 } {
  123. set dx [expr {$x0-$xb0}]
  124. }
  125. if { $x1 > $xb1+$dx } {
  126. set dx [expr {$x1-$xb1}]
  127. }
  128. }
  129. if { ![string compare $vert "top"] } {
  130. if { $y1 > $yb1 } {
  131. set dy [expr {$y1-$yb1}]
  132. }
  133. if { $y0 < $yb0+$dy } {
  134. set dy [expr {$y0-$yb0}]
  135. }
  136. } elseif { ![string compare $vert "bottom"] } {
  137. if { $y0 < $yb0 } {
  138. set dy [expr {$y0-$yb0}]
  139. }
  140. if { $y1 > $yb1+$dy } {
  141. set dy [expr {$y1-$yb1}]
  142. }
  143. }
  144. if { $dx != 0 } {
  145. set x [expr {($xb0+$dx)/[winfo width $path.frame]}]
  146. $path:cmd xview moveto $x
  147. }
  148. if { $dy != 0 } {
  149. set y [expr {($yb0+$dy)/[winfo height $path.frame]}]
  150. $path:cmd yview moveto $y
  151. }
  152. }
  153. # ------------------------------------------------------------------------------
  154. # Command ScrollableFrame::xview
  155. # ------------------------------------------------------------------------------
  156. proc ScrollableFrame::xview { path args } {
  157. return [eval $path:cmd xview $args]
  158. }
  159. # ------------------------------------------------------------------------------
  160. # Command ScrollableFrame::yview
  161. # ------------------------------------------------------------------------------
  162. proc ScrollableFrame::yview { path args } {
  163. return [eval $path:cmd yview $args]
  164. }
  165. # ------------------------------------------------------------------------------
  166. # Command ScrollableFrame::_resize
  167. # ------------------------------------------------------------------------------
  168. proc ScrollableFrame::_resize { path } {
  169. if { [Widget::getoption $path -constrainedwidth] } {
  170. $path:cmd itemconfigure win -width [winfo width $path]
  171. }
  172. if { [Widget::getoption $path -constrainedheight] } {
  173. $path:cmd itemconfigure win -height [winfo height $path]
  174. }
  175. }