I am trying to implement as TextView which automatically scrolls to display the latest added text unless there is any user scroll input.
Basically, the view auto-scrolls until the user does any scroll input or moves the slider bar, which has the effect of pausing the auto-scroll (text continues to be inserted).
When the user scrolls back to the bottom, auto-scroll resumes.
I still can’t figure out how to determine if the user has changed the position of the text/scrollview. I can add a scroll event controller but that only deals with the mouse scroll. There doesn’t seem to be a way to determine this from the Adjustment (the value of the adjustment constantly changes because the view is auto-scrolled).
I suggest the other way around: try to detect the text insertion, e.g. with Gtk.TextBuffer::insert-text , and if the adjustment value+page>=upper then perform the scroll.
That is a interesting idea but unfortunately but unfortunately, it doesn’t work. The problem is that the volume of text that gets inserted is large enough to cause the upper value to jump way past the value + page sum on the first signal callback:
You can calculate if we should scroll to bottom before adding the new text.
I implemented a similar behavior like this:
def add_to_terminal(line: str) -> None:
"""
add line to termianl in logs dialog
"""
terminal_text = get("LogsTextView")
buffer = terminal_text.get_buffer()
# Check if we're at the bottom.
scrolled_window = terminal_text.get_parent()
vadjustment = scrolled_window.get_vadjustment()
value = vadjustment.get_value()
upper = vadjustment.get_upper()
# Allow a third of window to still treat it as "at bottom".
page_size = vadjustment.get_page_size()
buffer_zone = page_size / 3
at_bottom = (value + page_size + buffer_zone) >= upper
# Insert text
buffer.insert(buffer.get_end_iter(), f"\n{line}\n")
# If we were at the bottom before, scroll to the new bottom.
if at_bottom:
mark = buffer.create_mark(None, buffer.get_end_iter(), False)
terminal_text.scroll_to_mark(mark, 0.0, False, 0.0, 0.0)
My issue is that the amount of text being inserted is very large. So, in the first iteration, checking value, upper and page_size works: value = 0, page_size = 400, and upper = 0. However, on the next iteration, upper is in the order of 15K. So the auto scroll does not work.
May be, I should split the text to be inserted into lines and add them line-by-line but I fear that will make things much slower.