scale.tcl 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. # scale.tcl --
  2. #
  3. # This file defines the default bindings for Tk scale widgets and provides
  4. # procedures that help in implementing the bindings.
  5. #
  6. # Copyright © 1994 The Regents of the University of California.
  7. # Copyright © 1994-1995 Sun Microsystems, Inc.
  8. #
  9. # See the file "license.terms" for information on usage and redistribution
  10. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11. #
  12. #-------------------------------------------------------------------------
  13. # The code below creates the default class bindings for entries.
  14. #-------------------------------------------------------------------------
  15. # Standard Motif bindings:
  16. bind Scale <Enter> {
  17. if {$tk_strictMotif} {
  18. set tk::Priv(activeBg) [%W cget -activebackground]
  19. %W configure -activebackground [%W cget -background]
  20. }
  21. tk::ScaleActivate %W %x %y
  22. }
  23. bind Scale <Motion> {
  24. tk::ScaleActivate %W %x %y
  25. }
  26. bind Scale <Leave> {
  27. if {$tk_strictMotif} {
  28. %W configure -activebackground $tk::Priv(activeBg)
  29. }
  30. if {[%W cget -state] eq "active"} {
  31. %W configure -state normal
  32. }
  33. }
  34. bind Scale <Button-1> {
  35. tk::ScaleButtonDown %W %x %y
  36. }
  37. bind Scale <B1-Motion> {
  38. tk::ScaleDrag %W %x %y
  39. }
  40. bind Scale <B1-Leave> { }
  41. bind Scale <B1-Enter> { }
  42. bind Scale <ButtonRelease-1> {
  43. tk::CancelRepeat
  44. tk::ScaleEndDrag %W
  45. tk::ScaleActivate %W %x %y
  46. }
  47. bind Scale <Button-2> {
  48. tk::ScaleButton2Down %W %x %y
  49. }
  50. bind Scale <B2-Motion> {
  51. tk::ScaleDrag %W %x %y
  52. }
  53. bind Scale <B2-Leave> { }
  54. bind Scale <B2-Enter> { }
  55. bind Scale <ButtonRelease-2> {
  56. tk::CancelRepeat
  57. tk::ScaleEndDrag %W
  58. tk::ScaleActivate %W %x %y
  59. }
  60. bind Scale <Control-Button-1> {
  61. tk::ScaleControlPress %W %x %y
  62. }
  63. bind Scale <<PrevLine>> {
  64. tk::ScaleIncrement %W up little noRepeat
  65. }
  66. bind Scale <<NextLine>> {
  67. tk::ScaleIncrement %W down little noRepeat
  68. }
  69. bind Scale <<PrevChar>> {
  70. tk::ScaleIncrement %W up little noRepeat
  71. }
  72. bind Scale <<NextChar>> {
  73. tk::ScaleIncrement %W down little noRepeat
  74. }
  75. bind Scale <<PrevPara>> {
  76. tk::ScaleIncrement %W up big noRepeat
  77. }
  78. bind Scale <<NextPara>> {
  79. tk::ScaleIncrement %W down big noRepeat
  80. }
  81. bind Scale <<PrevWord>> {
  82. tk::ScaleIncrement %W up big noRepeat
  83. }
  84. bind Scale <<NextWord>> {
  85. tk::ScaleIncrement %W down big noRepeat
  86. }
  87. bind Scale <<LineStart>> {
  88. %W set [%W cget -from]
  89. }
  90. bind Scale <<LineEnd>> {
  91. %W set [%W cget -to]
  92. }
  93. # ::tk::ScaleActivate --
  94. # This procedure is invoked to check a given x-y position in the
  95. # scale and activate the slider if the x-y position falls within
  96. # the slider.
  97. #
  98. # Arguments:
  99. # w - The scale widget.
  100. # x, y - Mouse coordinates.
  101. proc ::tk::ScaleActivate {w x y} {
  102. if {[$w cget -state] eq "disabled"} {
  103. return
  104. }
  105. if {[$w identify $x $y] eq "slider"} {
  106. set state active
  107. } else {
  108. set state normal
  109. }
  110. if {[$w cget -state] ne $state} {
  111. $w configure -state $state
  112. }
  113. }
  114. # ::tk::ScaleButtonDown --
  115. # This procedure is invoked when a button is pressed in a scale. It
  116. # takes different actions depending on where the button was pressed.
  117. #
  118. # Arguments:
  119. # w - The scale widget.
  120. # x, y - Mouse coordinates of button press.
  121. proc ::tk::ScaleButtonDown {w x y} {
  122. variable ::tk::Priv
  123. set Priv(dragging) 0
  124. set el [$w identify $x $y]
  125. # save the relief
  126. set Priv($w,relief) [$w cget -sliderrelief]
  127. if {$el eq "trough1"} {
  128. ScaleIncrement $w up little initial
  129. } elseif {$el eq "trough2"} {
  130. ScaleIncrement $w down little initial
  131. } elseif {$el eq "slider"} {
  132. set Priv(dragging) 1
  133. set Priv(initValue) [$w get]
  134. set coords [$w coords]
  135. set Priv(deltaX) [expr {$x - [lindex $coords 0]}]
  136. set Priv(deltaY) [expr {$y - [lindex $coords 1]}]
  137. switch -exact -- $Priv($w,relief) {
  138. "raised" { $w configure -sliderrelief sunken }
  139. "ridge" { $w configure -sliderrelief groove }
  140. }
  141. }
  142. }
  143. # ::tk::ScaleDrag --
  144. # This procedure is called when the mouse is dragged with
  145. # mouse button 1 down. If the drag started inside the slider
  146. # (i.e. the scale is active) then the scale's value is adjusted
  147. # to reflect the mouse's position.
  148. #
  149. # Arguments:
  150. # w - The scale widget.
  151. # x, y - Mouse coordinates.
  152. proc ::tk::ScaleDrag {w x y} {
  153. variable ::tk::Priv
  154. if {!$Priv(dragging)} {
  155. return
  156. }
  157. $w set [$w get [expr {$x-$Priv(deltaX)}] [expr {$y-$Priv(deltaY)}]]
  158. }
  159. # ::tk::ScaleEndDrag --
  160. # This procedure is called to end an interactive drag of the
  161. # slider. It just marks the drag as over.
  162. #
  163. # Arguments:
  164. # w - The scale widget.
  165. proc ::tk::ScaleEndDrag {w} {
  166. variable ::tk::Priv
  167. set Priv(dragging) 0
  168. if {[info exists Priv($w,relief)]} {
  169. $w configure -sliderrelief $Priv($w,relief)
  170. unset Priv($w,relief)
  171. }
  172. }
  173. # ::tk::ScaleIncrement --
  174. # This procedure is invoked to increment the value of a scale and
  175. # to set up auto-repeating of the action if that is desired. The
  176. # way the value is incremented depends on the "dir" and "big"
  177. # arguments.
  178. #
  179. # Arguments:
  180. # w - The scale widget.
  181. # dir - "up" means move value towards -from, "down" means
  182. # move towards -to.
  183. # big - Size of increments: "big" or "little".
  184. # repeat - Whether and how to auto-repeat the action: "noRepeat"
  185. # means don't auto-repeat, "initial" means this is the
  186. # first action in an auto-repeat sequence, and "again"
  187. # means this is the second repetition or later.
  188. proc ::tk::ScaleIncrement {w dir big repeat} {
  189. variable ::tk::Priv
  190. if {![winfo exists $w]} return
  191. # give the cancel callback a chance to be serviced if the execution time of
  192. # the -command script lasts longer than -repeatdelay
  193. set clockms [clock milliseconds]
  194. if {$repeat eq "again" &&
  195. [expr {$clockms - $Priv(clockms)}] > [expr {[$w cget -repeatinterval] * 1.1}]} {
  196. set Priv(clockms) $clockms
  197. set Priv(afterId) [after [$w cget -repeatinterval] \
  198. [list tk::ScaleIncrement $w $dir $big again]]
  199. return
  200. }
  201. if {$big eq "big"} {
  202. set inc [$w cget -bigincrement]
  203. if {$inc == 0} {
  204. set inc [expr {abs([$w cget -to] - [$w cget -from])/10.0}]
  205. }
  206. if {$inc < [$w cget -resolution]} {
  207. set inc [$w cget -resolution]
  208. }
  209. } else {
  210. set inc [$w cget -resolution]
  211. }
  212. if {([$w cget -from] > [$w cget -to]) ^ ($dir eq "up")} {
  213. if {$inc > 0} {
  214. set inc [expr {-$inc}]
  215. }
  216. } else {
  217. if {$inc < 0} {
  218. set inc [expr {-$inc}]
  219. }
  220. }
  221. # this will run the -command script (if any) during the redrawing
  222. # of the scale at idle time
  223. $w set [expr {[$w get] + $inc}]
  224. if {$repeat eq "again"} {
  225. set Priv(clockms) $clockms
  226. set Priv(afterId) [after [$w cget -repeatinterval] \
  227. [list tk::ScaleIncrement $w $dir $big again]]
  228. } elseif {$repeat eq "initial"} {
  229. set delay [$w cget -repeatdelay]
  230. if {$delay > 0} {
  231. set Priv(clockms) $clockms
  232. set Priv(afterId) [after $delay \
  233. [list tk::ScaleIncrement $w $dir $big again]]
  234. }
  235. }
  236. }
  237. # ::tk::ScaleControlPress --
  238. # This procedure handles button presses that are made with the Control
  239. # key down. Depending on the mouse position, it adjusts the scale
  240. # value to one end of the range or the other.
  241. #
  242. # Arguments:
  243. # w - The scale widget.
  244. # x, y - Mouse coordinates where the button was pressed.
  245. proc ::tk::ScaleControlPress {w x y} {
  246. set el [$w identify $x $y]
  247. if {$el eq "trough1"} {
  248. $w set [$w cget -from]
  249. } elseif {$el eq "trough2"} {
  250. $w set [$w cget -to]
  251. }
  252. }
  253. # ::tk::ScaleButton2Down
  254. # This procedure is invoked when button 2 is pressed over a scale.
  255. # It sets the value to correspond to the mouse position and starts
  256. # a slider drag.
  257. #
  258. # Arguments:
  259. # w - The scrollbar widget.
  260. # x, y - Mouse coordinates within the widget.
  261. proc ::tk::ScaleButton2Down {w x y} {
  262. variable ::tk::Priv
  263. if {[$w cget -state] eq "disabled"} {
  264. return
  265. }
  266. $w configure -state active
  267. $w set [$w get $x $y]
  268. set Priv(dragging) 1
  269. set Priv(initValue) [$w get]
  270. set Priv($w,relief) [$w cget -sliderrelief]
  271. set coords "$x $y"
  272. set Priv(deltaX) 0
  273. set Priv(deltaY) 0
  274. }