home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / lang / tcl / 2246 < prev    next >
Encoding:
Text File  |  1992-12-24  |  5.5 KB  |  229 lines

  1. Newsgroups: comp.lang.tcl
  2. Path: sparky!uunet!timbuk.cray.com!hemlock.cray.com!mgc
  3. From: mgc@cray.com (M. G. Christenson)
  4. Subject: Re: Automatic Scrolling
  5. Message-ID: <1992Dec24.011440.14385@hemlock.cray.com>
  6. Lines: 217
  7. Nntp-Posting-Host: pecan
  8. Reply-To: mgc@cray.com
  9. Organization: Cray Research, Inc.
  10. Date: 24 Dec 92 01:14:40 CST
  11.  
  12. >Hi,
  13. >
  14. >I am trying to implement automatic scrolling for scrollable canvas.
  15. >Instead of using the scroll bar, the canvas will be scrolling when
  16. >the mouse pointer is outside of the canvas. (The canvas will scroll
  17. >to the opposite direction of the location of the mouse pointer.)
  18. >(This feature is great when you want to drag a widget across a
  19. >scrollable canvas, so you can always see the widget at the edge
  20. >of the canvas.)
  21. >
  22. >I have tried to implement this feature through bindings. However
  23. >it does not work out nicely, since the events are not repeated.
  24. >
  25. >Has someone tried to accomplish similar task before?
  26. >Any input would be appreciated.
  27. >
  28. >Te-Wei Sun
  29. >tewei@bnr.ca
  30.  
  31. Here is the code I use, along with an example.  Hopefully the usage
  32. will be apparent from the example.
  33.  
  34. --Mark
  35.  
  36. proc autoscroll_var w {
  37.     global autoscroll_index
  38.  
  39.     if [info exists autoscroll_index($w)] {
  40.     return autoscroll.$autoscroll_index($w)
  41.     } else {
  42.     if [info exists autoscroll_index(next)] {
  43.         set next [expr {$autoscroll_index(next) + 1}]
  44.     } else {
  45.         set next 0
  46.     }
  47.     set autoscroll_index(next) $next
  48.     return autoscroll.[set autoscroll_index($w) $next]
  49.     }
  50. }
  51.  
  52. proc autoscroll_init \
  53.     {w delta_t {yscrollbar {}} {delta_y 1} {xscrollbar {}} {delta_x 1}} {
  54.     upvar #0 [autoscroll_var $w] v
  55.  
  56.     if {$delta_t == 0} {
  57.     catch {unset v}
  58.     return {}
  59.     }
  60.  
  61.     set v(autoscroll_delta_t) $delta_t
  62.     set v(autoscroll_delta_x) $delta_x
  63.     set v(autoscroll_delta_y) $delta_y
  64.  
  65.     set v(autoscroll_xscrollbar) $xscrollbar
  66.     if {$xscrollbar == {}} {
  67.     set v(autoscroll_dx) 0
  68.     }
  69.     set v(autoscroll_yscrollbar) $yscrollbar
  70.     if {$yscrollbar == {}} {
  71.     set v(autoscroll_dy) 0
  72.     }
  73.  
  74.     if {[trace vinfo v(autoscroll_dx)] == {}} {
  75.     set v(autoscrolling) 0
  76.     set v(autoscroll_dx) 0
  77.     set v(autoscroll_dy) 0
  78.  
  79.     trace variable v(autoscroll_dx) w "autoscroll $w"
  80.     trace variable v(autoscroll_dy) w "autoscroll $w"
  81.     }
  82.  
  83.     return {}
  84. }
  85.  
  86. proc autoscroll_event {w x y event} {
  87.     set cmd [bind $w $event]
  88.     if {$cmd == {}} {
  89.     set cmd [bind [winfo class $w] $event]
  90.     }
  91.     if {$cmd != {}} {
  92.     regsub -all W $cmd $w cmd
  93.     regsub -all 2bfa10 $cmd $x cmd
  94.     regsub -all y $cmd $y cmd
  95.     uplevel #0 $cmd
  96.     }
  97. }
  98.  
  99. proc autoscroll {w args} {
  100.     upvar #0 [autoscroll_var $w] v
  101.  
  102.     if {$args == {}} {
  103.     if $v(autoscroll_dx) {
  104.         set current [lindex [$v(autoscroll_xscrollbar) get] 2]
  105.         set cmd [lindex [$v(autoscroll_xscrollbar) config -command] 4]
  106.         eval $cmd [expr "$current + $v(autoscroll_dx)"]
  107.         if {$v(autoscroll_event) != {}} {
  108.         autoscroll_event $w $v(autoscroll_x) $v(autoscroll_y) \
  109.             $v(autoscroll_event)
  110.         }
  111.     }
  112.     if $v(autoscroll_dy) {
  113.         set current [lindex [$v(autoscroll_yscrollbar) get] 2]
  114.         set cmd [lindex [$v(autoscroll_yscrollbar) config -command] 4]
  115.         eval $cmd [expr "$current + $v(autoscroll_dy)"]
  116.         if {$v(autoscroll_event) != {}} {
  117.         autoscroll_event $w $v(autoscroll_x) $v(autoscroll_y) \
  118.             $v(autoscroll_event)
  119.         }
  120.     }
  121.     set v(autoscrolling) 0
  122.     }
  123.  
  124.     if {$v(autoscroll_dx) || $v(autoscroll_dy)} {
  125.     if !$v(autoscrolling) {
  126.         set v(autoscrolling) 1
  127.         after $v(autoscroll_delta_t) autoscroll $w
  128.     }
  129.     } else {
  130.     set v(autoscrolling) 0
  131.     }
  132. }
  133.  
  134. proc clear_autoscroll {w} {
  135.     upvar #0 [autoscroll_var $w] v
  136.  
  137.     if [info exists v] {
  138.     set v(autoscroll_dx) 0
  139.     set v(autoscroll_dy) 0
  140.     }
  141.     return {}
  142. }
  143.  
  144. proc check_autoscroll {w x y {event {}}} {
  145.     upvar #0 [autoscroll_var $w] v
  146.  
  147.     if ![info exists v] {
  148.     return {}
  149.     }
  150.  
  151.     set dx 0
  152.     if {$v(autoscroll_xscrollbar) != {}} {
  153.     if {$x < 0} {
  154.         set dx -$v(autoscroll_delta_x)
  155.     } else {
  156.         if {$x >= [winfo width $w]} {
  157.         set dx $v(autoscroll_delta_x)
  158.         }
  159.     }
  160.     }
  161.  
  162.     set dy 0
  163.     if {$v(autoscroll_yscrollbar) != {}} {
  164.     if {$y < 0} {
  165.         set dy -$v(autoscroll_delta_y)
  166.     } else {
  167.         if {$y >= [winfo height $w]} {
  168.         set dy $v(autoscroll_delta_y)
  169.         }
  170.     }
  171.     }
  172.  
  173.     set v(autoscroll_x) $x
  174.     set v(autoscroll_y) $y
  175.     set v(autoscroll_event) $event
  176.  
  177.     if {$v(autoscroll_dx) != $dx} {
  178.     set v(autoscroll_dx) $dx
  179.     }
  180.  
  181.     if {$v(autoscroll_dy) != $dy} {
  182.     set v(autoscroll_dy) $dy
  183.     }
  184.  
  185.     return {}
  186. }
  187.  
  188. proc bind_for_autoscroll {{classes {Text Listbox Canvas Entry}}} {
  189.     foreach class $classes {
  190.     bind $class <B1-Motion> {+check_autoscroll W 2c03bd y <B1-Motion>}
  191.     bind $class <Shift-B1-Motion> \
  192.         {+check_autoscroll W 2c0426 y <Shift-B1-Motion>}
  193.     bind $class <Any-ButtonRelease-1> {+clear_autoscroll W}
  194.     }
  195. }
  196.  
  197. proc autoscroll_example {} {
  198.     catch {destroy .example}
  199.  
  200.     frame .example
  201.     scrollbar .example.h -orient horizontal -command ".example.c xview"
  202.     scrollbar .example.v -command ".example.c yview"
  203.     canvas .example.c -confine 0 -xscrollcommand ".example.h set" \
  204.     -yscrollcommand ".example.v set"
  205.  
  206.     bind .example.c <1> {set x [W canvasx 2c05e9]; set y [W canvasy y]}
  207.     bind .example.c <B1-Motion> {
  208.     W delete oval
  209.     set xx  [W canvasx 2c066a]
  210.     set yy  [W canvasy y]
  211.     W create oval \
  212.         $x $y $xx $yy -tag oval -fill red
  213.     W config -scrollregion [W bbox withtag oval]
  214.     }
  215.  
  216.     autoscroll_init .example.c 100 .example.v 1 .example.h 1
  217.  
  218.     bind_for_autoscroll .example.c
  219.  
  220.     pack append .example \
  221.     .example.h {bottom fillx} \
  222.     .example.c {left expand fill} \
  223.     .example.v {left filly}
  224.  
  225.     pack append . .example {top expand fill}
  226. }
  227.  
  228.  
  229.