🐛 fix(ui): ensure scroll position is maintained after content updates in SmartScrolled widgets

This commit is contained in:
sankalp committed 2025-08-15 13:42:20 +05:45
1 parent 0f33293f5e
commit 52cb4362b7
1 file changed
-76
-76
View File
@@ -1,76 +0,0 @@
from gi.repository import Gtk, GLib
from fabric.widgets.box import Box
from fabric.widgets.scrolledwindow import ScrolledWindow
class SmartScrolledBox(Box):
def __init__(
self,
max_height: int = 300,
spacing: int = 6,
**kwargs,
):
super().__init__(orientation="v", spacing=spacing, **kwargs)
self._max_height = max_height
# The actual content box that holds children
self.content_box = Box(orientation="v", spacing=spacing)
# Viewport → for scrolling non-scrollable widgets like Box
self.viewport = Gtk.Viewport()
self.viewport.add(self.content_box)
# ScrolledWindow → wrapper for vertical scrolling
self.scroller = ScrolledWindow()
self.scroller.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
self.scroller.add(self.viewport)
self.add(self.scroller)
# Initial size check
GLib.idle_add(self._apply_height_constraint)
def append(self, widget: Gtk.Widget):
self.content_box.add(widget)
self._apply_height_constraint()
def remove(self, widget: Gtk.Widget):
self.content_box.remove(widget)
self._apply_height_constraint()
def clear(self):
for child in self.content_box.get_children():
self.content_box.remove(child)
self._apply_height_constraint()
def update_height(self):
"""Manually trigger height update - useful when content is added externally."""
self._apply_height_constraint()
def force_height_constraint(self):
"""Force height constraint immediately."""
self._apply_height_constraint()
def _apply_height_constraint(self):
"""Apply height constraint immediately without delay."""
_, nat_height = self.content_box.get_preferred_height()
if nat_height > self._max_height:
# Force height constraint and show scrollbar
self.set_size_request(-1, self._max_height)
self.scroller.set_size_request(-1, self._max_height)
self.scroller.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.ALWAYS)
else:
# Allow natural height, no size request
self.set_size_request(-1, -1)
self.scroller.set_size_request(-1, -1)
self.scroller.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER)
def get_vadjustment(self):
"""Get the vertical adjustment from the scrolled window."""
return self.scroller.get_vadjustment()
def get_hadjustment(self):
"""Get the horizontal adjustment from the scrolled window."""
return self.scroller.get_hadjustment()