NavWidget: support programmatic dismiss (#37486)

* add dismiss support

* add to widget

* use in dialogs

* good catch

* fix!!

* fix!!

* it works eitehr way

* frick

* good catch
This commit is contained in:
Shane Smiskol
2026-02-28 07:16:06 -08:00
committed by GitHub
parent e244aabe88
commit 9cc0d7a1c9
4 changed files with 26 additions and 7 deletions
+6
View File
@@ -195,3 +195,9 @@ class Widget(abc.ABC):
def hide_event(self):
"""Optionally handle hide event. Parent must manually call this"""
def dismiss(self, callback: Callable[[], None] | None = None):
"""Immediately dismiss the widget, firing the callback after."""
gui_app.pop_widget()
if callback:
callback()
+15
View File
@@ -2,6 +2,7 @@ from __future__ import annotations
import abc
import pyray as rl
from collections.abc import Callable
from openpilot.system.ui.widgets import Widget
from openpilot.common.filter_simple import BounceFilter, FirstOrderFilter
from openpilot.system.ui.lib.application import gui_app, MousePos, MouseEvent
@@ -15,6 +16,7 @@ NAV_BAR_WIDTH = 205
NAV_BAR_HEIGHT = 8
DISMISS_PUSH_OFFSET = NAV_BAR_MARGIN + NAV_BAR_HEIGHT + 50 # px extra to push down when dismissing
DISMISS_ANIMATION_RC = 0.2 # slightly slower for non-user triggered dismiss animation
class NavBar(Widget):
@@ -61,6 +63,8 @@ class NavWidget(Widget, abc.ABC):
self._playing_dismiss_animation = False # released and animating away
self._y_pos_filter = BounceFilter(0.0, 0.1, 1 / gui_app.target_fps, bounce=1)
self._dismiss_callback: Callable[[], None] | None = None
# TODO: move this state into NavBar
self._nav_bar = NavBar()
self._nav_bar_show_time = 0.0
@@ -141,6 +145,9 @@ class NavWidget(Widget, abc.ABC):
if new_y > self._rect.height + DISMISS_PUSH_OFFSET - 10:
gui_app.pop_widget()
if self._dismiss_callback is not None:
self._dismiss_callback()
self._dismiss_callback = None
self._playing_dismiss_animation = False
self._drag_start_pos = None
@@ -180,6 +187,13 @@ class NavWidget(Widget, abc.ABC):
def is_dismissing(self) -> bool:
return self._dragging_down or self._playing_dismiss_animation
def dismiss(self, callback: Callable[[], None] | None = None):
"""Programmatically trigger the dismiss animation. Calls pop_widget when done, then callback."""
if not self._playing_dismiss_animation:
self._playing_dismiss_animation = True
self._y_pos_filter.update_alpha(DISMISS_ANIMATION_RC)
self._dismiss_callback = callback
def show_event(self):
super().show_event()
self._nav_bar.show_event()
@@ -188,6 +202,7 @@ class NavWidget(Widget, abc.ABC):
self._drag_start_pos = None
self._dragging_down = False
self._playing_dismiss_animation = False
self._dismiss_callback = None
# Start NavWidget off-screen, no matter how tall it is
self._y_pos_filter.update_alpha(0.1)
self._y_pos_filter.x = gui_app.height