scrlbar.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
源码类别:

通讯编程

开发平台:

Visual C++

  1. # scrlbar.tcl --
  2. #
  3. # This file defines the default bindings for Tk scrollbar widgets.
  4. # It also provides procedures that help in implementing the bindings.
  5. #
  6. # RCS: @(#) $Id: scrlbar.tcl,v 1.10.2.3 2006/03/17 10:50:11 patthoyts Exp $
  7. #
  8. # Copyright (c) 1994 The Regents of the University of California.
  9. # Copyright (c) 1994-1996 Sun Microsystems, Inc.
  10. #
  11. # See the file "license.terms" for information on usage and redistribution
  12. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13. #
  14. #-------------------------------------------------------------------------
  15. # The code below creates the default class bindings for scrollbars.
  16. #-------------------------------------------------------------------------
  17. # Standard Motif bindings:
  18. if {[tk windowingsystem] eq "x11"} {
  19. bind Scrollbar <Enter> {
  20.     if {$tk_strictMotif} {
  21. set tk::Priv(activeBg) [%W cget -activebackground]
  22. %W configure -activebackground [%W cget -background]
  23.     }
  24.     %W activate [%W identify %x %y]
  25. }
  26. bind Scrollbar <Motion> {
  27.     %W activate [%W identify %x %y]
  28. }
  29. # The "info exists" command in the following binding handles the
  30. # situation where a Leave event occurs for a scrollbar without the Enter
  31. # event.  This seems to happen on some systems (such as Solaris 2.4) for
  32. # unknown reasons.
  33. bind Scrollbar <Leave> {
  34.     if {$tk_strictMotif && [info exists tk::Priv(activeBg)]} {
  35. %W configure -activebackground $tk::Priv(activeBg)
  36.     }
  37.     %W activate {}
  38. }
  39. bind Scrollbar <1> {
  40.     tk::ScrollButtonDown %W %x %y
  41. }
  42. bind Scrollbar <B1-Motion> {
  43.     tk::ScrollDrag %W %x %y
  44. }
  45. bind Scrollbar <B1-B2-Motion> {
  46.     tk::ScrollDrag %W %x %y
  47. }
  48. bind Scrollbar <ButtonRelease-1> {
  49.     tk::ScrollButtonUp %W %x %y
  50. }
  51. bind Scrollbar <B1-Leave> {
  52.     # Prevents <Leave> binding from being invoked.
  53. }
  54. bind Scrollbar <B1-Enter> {
  55.     # Prevents <Enter> binding from being invoked.
  56. }
  57. bind Scrollbar <2> {
  58.     tk::ScrollButton2Down %W %x %y
  59. }
  60. bind Scrollbar <B1-2> {
  61.     # Do nothing, since button 1 is already down.
  62. }
  63. bind Scrollbar <B2-1> {
  64.     # Do nothing, since button 2 is already down.
  65. }
  66. bind Scrollbar <B2-Motion> {
  67.     tk::ScrollDrag %W %x %y
  68. }
  69. bind Scrollbar <ButtonRelease-2> {
  70.     tk::ScrollButtonUp %W %x %y
  71. }
  72. bind Scrollbar <B1-ButtonRelease-2> {
  73.     # Do nothing:  B1 release will handle it.
  74. }
  75. bind Scrollbar <B2-ButtonRelease-1> {
  76.     # Do nothing:  B2 release will handle it.
  77. }
  78. bind Scrollbar <B2-Leave> {
  79.     # Prevents <Leave> binding from being invoked.
  80. }
  81. bind Scrollbar <B2-Enter> {
  82.     # Prevents <Enter> binding from being invoked.
  83. }
  84. bind Scrollbar <Control-1> {
  85.     tk::ScrollTopBottom %W %x %y
  86. }
  87. bind Scrollbar <Control-2> {
  88.     tk::ScrollTopBottom %W %x %y
  89. }
  90. bind Scrollbar <Up> {
  91.     tk::ScrollByUnits %W v -1
  92. }
  93. bind Scrollbar <Down> {
  94.     tk::ScrollByUnits %W v 1
  95. }
  96. bind Scrollbar <Control-Up> {
  97.     tk::ScrollByPages %W v -1
  98. }
  99. bind Scrollbar <Control-Down> {
  100.     tk::ScrollByPages %W v 1
  101. }
  102. bind Scrollbar <Left> {
  103.     tk::ScrollByUnits %W h -1
  104. }
  105. bind Scrollbar <Right> {
  106.     tk::ScrollByUnits %W h 1
  107. }
  108. bind Scrollbar <Control-Left> {
  109.     tk::ScrollByPages %W h -1
  110. }
  111. bind Scrollbar <Control-Right> {
  112.     tk::ScrollByPages %W h 1
  113. }
  114. bind Scrollbar <Prior> {
  115.     tk::ScrollByPages %W hv -1
  116. }
  117. bind Scrollbar <Next> {
  118.     tk::ScrollByPages %W hv 1
  119. }
  120. bind Scrollbar <Home> {
  121.     tk::ScrollToPos %W 0
  122. }
  123. bind Scrollbar <End> {
  124.     tk::ScrollToPos %W 1
  125. }
  126. }
  127. if {[tk windowingsystem] eq "classic" || [tk windowingsystem] eq "aqua"} {
  128.     bind Scrollbar <MouseWheel> {
  129.         tk::ScrollByUnits %W v [expr {- (%D)}]
  130.     }
  131.     bind Scrollbar <Option-MouseWheel> {
  132.         tk::ScrollByUnits %W v [expr {-10 * (%D)}]
  133.     }
  134.     bind Scrollbar <Shift-MouseWheel> {
  135.         tk::ScrollByUnits %W h [expr {- (%D)}]
  136.     }
  137.     bind Scrollbar <Shift-Option-MouseWheel> {
  138.         tk::ScrollByUnits %W h [expr {-10 * (%D)}]
  139.     }
  140. }
  141. # tk::ScrollButtonDown --
  142. # This procedure is invoked when a button is pressed in a scrollbar.
  143. # It changes the way the scrollbar is displayed and takes actions
  144. # depending on where the mouse is.
  145. #
  146. # Arguments:
  147. # w - The scrollbar widget.
  148. # x, y - Mouse coordinates.
  149. proc tk::ScrollButtonDown {w x y} {
  150.     variable ::tk::Priv
  151.     set Priv(relief) [$w cget -activerelief]
  152.     $w configure -activerelief sunken
  153.     set element [$w identify $x $y]
  154.     if {$element eq "slider"} {
  155. ScrollStartDrag $w $x $y
  156.     } else {
  157. ScrollSelect $w $element initial
  158.     }
  159. }
  160. # ::tk::ScrollButtonUp --
  161. # This procedure is invoked when a button is released in a scrollbar.
  162. # It cancels scans and auto-repeats that were in progress, and restores
  163. # the way the active element is displayed.
  164. #
  165. # Arguments:
  166. # w - The scrollbar widget.
  167. # x, y - Mouse coordinates.
  168. proc ::tk::ScrollButtonUp {w x y} {
  169.     variable ::tk::Priv
  170.     tk::CancelRepeat
  171.     if {[info exists Priv(relief)]} {
  172. # Avoid error due to spurious release events
  173. $w configure -activerelief $Priv(relief)
  174. ScrollEndDrag $w $x $y
  175. $w activate [$w identify $x $y]
  176.     }
  177. }
  178. # ::tk::ScrollSelect --
  179. # This procedure is invoked when a button is pressed over the scrollbar.
  180. # It invokes one of several scrolling actions depending on where in
  181. # the scrollbar the button was pressed.
  182. #
  183. # Arguments:
  184. # w - The scrollbar widget.
  185. # element - The element of the scrollbar that was selected, such
  186. # as "arrow1" or "trough2".  Shouldn't be "slider".
  187. # repeat - Whether and how to auto-repeat the action:  "noRepeat"
  188. # means don't auto-repeat, "initial" means this is the
  189. # first action in an auto-repeat sequence, and "again"
  190. # means this is the second repetition or later.
  191. proc ::tk::ScrollSelect {w element repeat} {
  192.     variable ::tk::Priv
  193.     if {![winfo exists $w]} return
  194.     switch -- $element {
  195. "arrow1" {ScrollByUnits $w hv -1}
  196. "trough1" {ScrollByPages $w hv -1}
  197. "trough2" {ScrollByPages $w hv 1}
  198. "arrow2" {ScrollByUnits $w hv 1}
  199. default {return}
  200.     }
  201.     if {$repeat eq "again"} {
  202. set Priv(afterId) [after [$w cget -repeatinterval] 
  203. [list tk::ScrollSelect $w $element again]]
  204.     } elseif {$repeat eq "initial"} {
  205. set delay [$w cget -repeatdelay]
  206. if {$delay > 0} {
  207.     set Priv(afterId) [after $delay 
  208.     [list tk::ScrollSelect $w $element again]]
  209. }
  210.     }
  211. }
  212. # ::tk::ScrollStartDrag --
  213. # This procedure is called to initiate a drag of the slider.  It just
  214. # remembers the starting position of the mouse and slider.
  215. #
  216. # Arguments:
  217. # w - The scrollbar widget.
  218. # x, y - The mouse position at the start of the drag operation.
  219. proc ::tk::ScrollStartDrag {w x y} {
  220.     variable ::tk::Priv
  221.     if {[$w cget -command] eq ""} {
  222. return
  223.     }
  224.     set Priv(pressX) $x
  225.     set Priv(pressY) $y
  226.     set Priv(initValues) [$w get]
  227.     set iv0 [lindex $Priv(initValues) 0]
  228.     if {[llength $Priv(initValues)] == 2} {
  229. set Priv(initPos) $iv0
  230.     } elseif {$iv0 == 0} {
  231. set Priv(initPos) 0.0
  232.     } else {
  233. set Priv(initPos) [expr {(double([lindex $Priv(initValues) 2])) 
  234. / [lindex $Priv(initValues) 0]}]
  235.     }
  236. }
  237. # ::tk::ScrollDrag --
  238. # This procedure is called for each mouse motion even when the slider
  239. # is being dragged.  It notifies the associated widget if we're not
  240. # jump scrolling, and it just updates the scrollbar if we are jump
  241. # scrolling.
  242. #
  243. # Arguments:
  244. # w - The scrollbar widget.
  245. # x, y - The current mouse position.
  246. proc ::tk::ScrollDrag {w x y} {
  247.     variable ::tk::Priv
  248.     if {$Priv(initPos) eq ""} {
  249. return
  250.     }
  251.     set delta [$w delta [expr {$x - $Priv(pressX)}] [expr {$y - $Priv(pressY)}]]
  252.     if {[$w cget -jump]} {
  253. if {[llength $Priv(initValues)] == 2} {
  254.     $w set [expr {[lindex $Priv(initValues) 0] + $delta}] 
  255.     [expr {[lindex $Priv(initValues) 1] + $delta}]
  256. } else {
  257.     set delta [expr {round($delta * [lindex $Priv(initValues) 0])}]
  258.     eval [list $w] set [lreplace $Priv(initValues) 2 3 
  259.     [expr {[lindex $Priv(initValues) 2] + $delta}] 
  260.     [expr {[lindex $Priv(initValues) 3] + $delta}]]
  261. }
  262.     } else {
  263. ScrollToPos $w [expr {$Priv(initPos) + $delta}]
  264.     }
  265. }
  266. # ::tk::ScrollEndDrag --
  267. # This procedure is called to end an interactive drag of the slider.
  268. # It scrolls the window if we're in jump mode, otherwise it does nothing.
  269. #
  270. # Arguments:
  271. # w - The scrollbar widget.
  272. # x, y - The mouse position at the end of the drag operation.
  273. proc ::tk::ScrollEndDrag {w x y} {
  274.     variable ::tk::Priv
  275.     if {$Priv(initPos) eq ""} {
  276. return
  277.     }
  278.     if {[$w cget -jump]} {
  279. set delta [$w delta [expr {$x - $Priv(pressX)}] 
  280. [expr {$y - $Priv(pressY)}]]
  281. ScrollToPos $w [expr {$Priv(initPos) + $delta}]
  282.     }
  283.     set Priv(initPos) ""
  284. }
  285. # ::tk::ScrollByUnits --
  286. # This procedure tells the scrollbar's associated widget to scroll up
  287. # or down by a given number of units.  It notifies the associated widget
  288. # in different ways for old and new command syntaxes.
  289. #
  290. # Arguments:
  291. # w - The scrollbar widget.
  292. # orient - Which kinds of scrollbars this applies to:  "h" for
  293. # horizontal, "v" for vertical, "hv" for both.
  294. # amount - How many units to scroll:  typically 1 or -1.
  295. proc ::tk::ScrollByUnits {w orient amount} {
  296.     set cmd [$w cget -command]
  297.     if {$cmd eq "" || ([string first [string index [$w cget -orient] 0] $orient] < 0)} {
  298. return
  299.     }
  300.     set info [$w get]
  301.     if {[llength $info] == 2} {
  302. uplevel #0 $cmd scroll $amount units
  303.     } else {
  304. uplevel #0 $cmd [expr {[lindex $info 2] + $amount}]
  305.     }
  306. }
  307. # ::tk::ScrollByPages --
  308. # This procedure tells the scrollbar's associated widget to scroll up
  309. # or down by a given number of screenfuls.  It notifies the associated
  310. # widget in different ways for old and new command syntaxes.
  311. #
  312. # Arguments:
  313. # w - The scrollbar widget.
  314. # orient - Which kinds of scrollbars this applies to:  "h" for
  315. # horizontal, "v" for vertical, "hv" for both.
  316. # amount - How many screens to scroll:  typically 1 or -1.
  317. proc ::tk::ScrollByPages {w orient amount} {
  318.     set cmd [$w cget -command]
  319.     if {$cmd eq "" || ([string first [string index [$w cget -orient] 0] $orient] < 0)} {
  320. return
  321.     }
  322.     set info [$w get]
  323.     if {[llength $info] == 2} {
  324. uplevel #0 $cmd scroll $amount pages
  325.     } else {
  326. uplevel #0 $cmd [expr {[lindex $info 2] + $amount*([lindex $info 1] - 1)}]
  327.     }
  328. }
  329. # ::tk::ScrollToPos --
  330. # This procedure tells the scrollbar's associated widget to scroll to
  331. # a particular location, given by a fraction between 0 and 1.  It notifies
  332. # the associated widget in different ways for old and new command syntaxes.
  333. #
  334. # Arguments:
  335. # w - The scrollbar widget.
  336. # pos - A fraction between 0 and 1 indicating a desired position
  337. # in the document.
  338. proc ::tk::ScrollToPos {w pos} {
  339.     set cmd [$w cget -command]
  340.     if {$cmd eq ""} {
  341. return
  342.     }
  343.     set info [$w get]
  344.     if {[llength $info] == 2} {
  345. uplevel #0 $cmd moveto $pos
  346.     } else {
  347. uplevel #0 $cmd [expr {round([lindex $info 0]*$pos)}]
  348.     }
  349. }
  350. # ::tk::ScrollTopBottom
  351. # Scroll to the top or bottom of the document, depending on the mouse
  352. # position.
  353. #
  354. # Arguments:
  355. # w - The scrollbar widget.
  356. # x, y - Mouse coordinates within the widget.
  357. proc ::tk::ScrollTopBottom {w x y} {
  358.     variable ::tk::Priv
  359.     set element [$w identify $x $y]
  360.     if {[string match *1 $element]} {
  361. ScrollToPos $w 0
  362.     } elseif {[string match *2 $element]} {
  363. ScrollToPos $w 1
  364.     }
  365.     # Set Priv(relief), since it's needed by tk::ScrollButtonUp.
  366.     set Priv(relief) [$w cget -activerelief]
  367. }
  368. # ::tk::ScrollButton2Down
  369. # This procedure is invoked when button 2 is pressed over a scrollbar.
  370. # If the button is over the trough or slider, it sets the scrollbar to
  371. # the mouse position and starts a slider drag.  Otherwise it just
  372. # behaves the same as button 1.
  373. #
  374. # Arguments:
  375. # w - The scrollbar widget.
  376. # x, y - Mouse coordinates within the widget.
  377. proc ::tk::ScrollButton2Down {w x y} {
  378.     variable ::tk::Priv
  379.     set element [$w identify $x $y]
  380.     if {[string match {arrow[12]} $element]} {
  381. ScrollButtonDown $w $x $y
  382. return
  383.     }
  384.     ScrollToPos $w [$w fraction $x $y]
  385.     set Priv(relief) [$w cget -activerelief]
  386.     # Need the "update idletasks" below so that the widget calls us
  387.     # back to reset the actual scrollbar position before we start the
  388.     # slider drag.
  389.     update idletasks
  390.     $w configure -activerelief sunken
  391.     $w activate slider
  392.     ScrollStartDrag $w $x $y
  393. }