feat(src/shared/window): addanimated scrollable window and close_applet cleanup
Introduce Animator‑driven height transitions for smoother scrolling and ensure proper cleanup when the applet window closes.
This commit is contained in:
2 files changed
+69
No files matched your search
@@ -0,0 +1,68 @@
|
||||
from fabric.widgets.scrolledwindow import ScrolledWindow
|
||||
|
||||
from shared.widgets.animator import Animator
|
||||
|
||||
|
||||
class AnimatedScrollable(ScrolledWindow):
|
||||
def __init__(
|
||||
self,
|
||||
bezier_curve: tuple[float, float, float, float] = (0.2, 1, 0.8, 1.0),
|
||||
duration: float = 0.3,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
self._last_req = -1
|
||||
_, min_height = self.min_content_size
|
||||
_, max_height = self.max_content_size
|
||||
|
||||
self.height_animator = Animator(
|
||||
bezier_curve=bezier_curve,
|
||||
duration=duration,
|
||||
min_value=min_height,
|
||||
max_value=max_height,
|
||||
)
|
||||
self.height_animator.connect("notify::value", self.on_animator_change)
|
||||
self.set_overlay_scrolling(True)
|
||||
|
||||
self.connect("notify::child", self._on_child_notified)
|
||||
if self.get_child():
|
||||
self._on_child_notified()
|
||||
|
||||
def _on_child_notified(self, *_):
|
||||
child = self.get_child()
|
||||
if child:
|
||||
child.connect("size-allocate", self._on_child_size_allocate)
|
||||
|
||||
def _on_child_size_allocate(self, widget, allocation):
|
||||
_, nat_height = widget.get_preferred_height()
|
||||
target = min(nat_height, self.max_content_size[1])
|
||||
if target != self._last_req:
|
||||
self.animate_size(target)
|
||||
|
||||
def on_animator_change(self, animator: Animator, *_):
|
||||
value = round(animator.value)
|
||||
self.set_min_content_height(value)
|
||||
self.queue_resize()
|
||||
|
||||
def do_animate(
|
||||
self,
|
||||
from_height: int = 0,
|
||||
to_height: int = -1,
|
||||
):
|
||||
if to_height == -1:
|
||||
return
|
||||
self.height_animator.pause()
|
||||
self.height_animator.min_value = from_height
|
||||
self.height_animator.max_value = to_height
|
||||
self.height_animator.play()
|
||||
return
|
||||
|
||||
def animate_size(self, height: int = -1):
|
||||
self._last_req = height
|
||||
current_val = self.height_animator.value
|
||||
return self.do_animate(current_val, height)
|
||||
|
||||
def do_get_preferred_height(self):
|
||||
value = self.height_animator.value
|
||||
value = 0 if value < 0 else value
|
||||
return value, value
|
||||
@@ -70,6 +70,7 @@ class AppletWindow(PopupWindow):
|
||||
self.set_focus(None)
|
||||
|
||||
def close_applet(self):
|
||||
|
||||
if not self._is_open:
|
||||
return
|
||||
|
||||
|
||||
Reference in new issue
Block a user