Does anyone know how I can give depth to the "scroll" manually instead of using "yview"?
Example:
pack [frame .top.frm -bg #efefef] -side left -anchor nw
set dir $env(HOME)
set total [llength [glob -nocomplain -directory $dir -tails *]]
pack [scrollbar .top.frm.sbr -orient vertical -command ".top.frm.txt $total"] -side right -fill y
pack [text .top.frm.txt -bg #efefef -yscrollcommand ".top.frm.sbr set" -wrap word] -side left -anchor nw -fill both -expand true -padx 0 -pady 0
...
.top.frm.txt window create end -window $panel
bind .top.frm.txt <Configure> {
%W.pnl configure -width [expr {%w - 5}] -height [expr {%h - 5}]
}
pack propagate $panel 0
Instead of using "yview" I want to pass a variable (in this example case it is - $total) with the total number of elements to be counted in order for the scroll to give the proper depth of movement vertically.
Before:
pack [scrollbar .top.frm.sbr -orient vertical -command ".top.frm.txt yview"]
After:
pack [scrollbar .top.frm.sbr -orient vertical -command ".top.frm.txt $total"]
I am asking because I could not find a solution by searching the Internet.
The yview
method still needs to be called, as it is how the vertical position is set by the scrollbar, but it doesn't need to be called directly. (Similarly, the $scrollbar set
method in the -yscrollcommand
option doesn't need to be called directly either; it's called to inform the scrollbar what the current window is.)
For the text→scrollbar direction, the set
method accepts 2 arguments and is used to describe what the current window is. The first argument is the proportion through the content of the start of the window, the second is the proportion of the end of the window, with both being floats. The callback is called when the rendering of the content of the window is redrawn.
For the scrollbar→text direction, things are more complex because there are two possible protocols and the system guesses which to use. (My advice: make sure you have exactly two words in your callback.) It's used to tell the scrolled widget what motion the user has specified with the scrollbar; when you click in the scrollbar, it calls through this, and doesn't move the scrollbar directly (that happens when the text widget calls back in the other direction).
If you are faking where the window is, you need to intercept the text→scrollbar direction. (Maybe the other way as well.)
If you are driving multiple widgets off one scrollbar, you need to intercept the scrollbar→text direction. (Maybe the other way as well.)
In your case, you're intercepting the scrollbar→text direction. To do the interception, you should use a procedure or an object. (Either works.)
proc interceptScrolling {callbackDetails args} {
# Unpack the arguments provided via the callback definition
lassign $callbackDetails targetWidget method total
# Not quite sure what you want to do in here
puts "total=$total args=$args"
# Pass the key things through to the target widget
$targetWidget $method {*}$args
}
# Build the callback like this
pack [scrollbar .top.frm.sbr -orient vertical \
-command [list interceptScrolling [list .top.frm.txt yview $total]]] \
-side right -fill y
or
oo::class create VerticalScrollbarIntercept {
variable targetWidget total
constructor {w tot} {
set targetWidget $w
set total $tot
}
method yview args {
puts "total=$total args=$args"
$targetWidget yview {*}$args
}
# Override construction to let us pack the method name too
self method new {targetWidget total} {
return [list [next $targetWidget $total] yview]
}
}
# Build the callback like this
pack [scrollbar .top.frm.sbr -orient vertical \
-command [VerticalScrollbarIntercept new .top.frm.txt $total]] \
-side right -fill y