Skip to content

Commit

Permalink
feat(MenuWidget): add go_home method, resetting the stack to a sing…
Browse files Browse the repository at this point in the history
…le element root menu
  • Loading branch information
sassanh committed May 8, 2024
1 parent 2ec1f20 commit 9076fca
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 30 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Version 0.11.7

- feat(MenuWidget): add `go_home` method, resetting the stack to a single element
root menu

## Version 0.11.6

- refactor(MenuWidget): dispatch `on_close` event on the `PageWidget` instance when
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "ubo-gui"
version = "0.11.6"
version = "0.11.7"
description = "GUI sdk for Ubo Pod"
authors = ["Sassan Haradji <[email protected]>"]
license = "Apache-2.0"
Expand Down
72 changes: 44 additions & 28 deletions ubo_gui/menu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,18 @@ def __init__(self: MenuWidget, **kwargs: object) -> None:
self.screen_subscriptions_lock = threading.Lock()
self.stack_lock = threading.Lock()
super().__init__(**kwargs)
self.bind(stack=self.render)
self.bind(stack=self._render)

def __del__(self: MenuWidget) -> None:
"""Clear all subscriptions."""
self.clear_widget_subscriptions()
self.clear_screen_subscriptions()
self._clear_widget_subscriptions()
self._clear_screen_subscriptions()

def set_root_menu(self: MenuWidget, root_menu: Menu) -> None:
"""Set the root menu."""
self.stack = []
self.push(root_menu, transition=self._no_transition)
with self.stack_lock:
self.stack = []
self._push(root_menu, transition=self._no_transition)

def get_depth(self: MenuWidget) -> int:
"""Return depth of the current screen."""
Expand Down Expand Up @@ -171,7 +172,7 @@ def go_down(self: MenuWidget) -> None:
if self.pages == 1:
return
self.page_index = (self.page_index + 1) % self.pages
self.render_items()
self._render_items()
self._switch_to(
self.current_screen,
transition=self._slide_transition,
Expand All @@ -190,7 +191,7 @@ def go_up(self: MenuWidget) -> None:
if self.pages == 1:
return
self.page_index = (self.page_index - 1) % self.pages
self.render_items()
self._render_items()
self._switch_to(
self.current_screen,
transition=self._slide_transition,
Expand All @@ -211,10 +212,15 @@ def handle_menu_change(menu: Menu) -> None:
'subscription_level': 'parent',
},
)
if last_sub_menu:
self.replace(menu)
else:
self.push(menu, transition=self._slide_transition, direction='left')
with self.stack_lock:
if last_sub_menu:
self._replace(menu)
else:
self._push(
menu,
transition=self._slide_transition,
direction='left',
)
last_sub_menu = menu

susbscription = process_subscribable_value(
Expand Down Expand Up @@ -297,9 +303,19 @@ def go_back(self: MenuWidget) -> None:
if not self.current_application.go_back():
self.close_application(self.current_application)
elif self.current_menu:
self.pop()
with self.stack_lock:
self._pop()

def go_home(self: MenuWidget) -> None:
"""Go back to the root menu."""
with self.stack_lock:
self.stack = self.stack[:1]
self._switch_to(
self.current_screen,
transition=self._rise_in_transition,
)

def render_header_menu(self: MenuWidget, menu: HeadedMenu) -> HeaderMenuPageWidget:
def _render_header_menu(self: MenuWidget, menu: HeadedMenu) -> HeaderMenuPageWidget:
"""Render a header menu."""
next_item = (
None
Expand Down Expand Up @@ -363,7 +379,7 @@ def handle_sub_heading_change(sub_heading: str) -> None:

return list_widget

def render_normal_menu(self: MenuWidget, menu: Menu) -> NormalMenuPageWidget:
def _render_normal_menu(self: MenuWidget, menu: Menu) -> NormalMenuPageWidget:
"""Render a normal menu."""
offset = -(PAGE_SIZE - 1) if isinstance(menu, HeadedMenu) else 0
items: list[Item | None] = list(
Expand Down Expand Up @@ -417,17 +433,17 @@ def render_normal_menu(self: MenuWidget, menu: Menu) -> NormalMenuPageWidget:
padding_top=self.padding_top,
)

def render_items(self: MenuWidget, *_: object) -> None:
def _render_items(self: MenuWidget, *_: object) -> None:
"""Render the items of the current menu."""
self.clear_widget_subscriptions()
self._clear_widget_subscriptions()
if self.page_index >= self.pages:
self.page_index = self.pages - 1
if not self.current_menu:
return
if self.page_index == 0 and isinstance(self.current_menu, HeadedMenu):
list_widget = self.render_header_menu(self.current_menu)
list_widget = self._render_header_menu(self.current_menu)
else:
list_widget = self.render_normal_menu(self.current_menu)
list_widget = self._render_normal_menu(self.current_menu)

self.current_screen = list_widget

Expand All @@ -450,9 +466,9 @@ def handle_placeholder_change(placeholder: str | None) -> None:
),
)

def render(self: MenuWidget, *_: object) -> None:
def _render(self: MenuWidget, *_: object) -> None:
"""Return the current screen page."""
self.clear_screen_subscriptions()
self._clear_screen_subscriptions()

if not self.stack:
return
Expand All @@ -477,7 +493,7 @@ def handle_items_change(items: Sequence[Item]) -> None:
)
if items != last_items:
self.current_menu_items = items
self.render_items()
self._render_items()
if last_items:
self._switch_to(
self.current_screen,
Expand Down Expand Up @@ -529,7 +545,7 @@ def open_application(self: MenuWidget, application: PageWidget) -> None:
application.name = uuid.uuid4().hex
application.padding_bottom = self.padding_bottom
application.padding_top = self.padding_top
self.push(
self._push(
application,
transition=self._swap_transition,
duration=0.2,
Expand Down Expand Up @@ -566,7 +582,7 @@ def close_application(self: MenuWidget, application: PageWidget) -> None:
isinstance(self.top.root, StackApplicationItem)
and self.top.root.application is application
):
self.pop()
self._pop()

@property
def top(self: MenuWidget) -> StackItem:
Expand All @@ -576,7 +592,7 @@ def top(self: MenuWidget) -> StackItem:
raise IndexError(msg)
return self.stack[-1]

def replace(
def _replace(
self: MenuWidget,
item: Menu | PageWidget,
) -> None:
Expand All @@ -600,7 +616,7 @@ def replace(
transition=self._no_transition,
)

def push( # noqa: PLR0913
def _push( # noqa: PLR0913
self: MenuWidget,
item: Menu | PageWidget,
/,
Expand Down Expand Up @@ -629,7 +645,7 @@ def push( # noqa: PLR0913
direction=direction,
)

def pop(
def _pop(
self: MenuWidget,
/,
*,
Expand Down Expand Up @@ -667,15 +683,15 @@ def on_kv_post(self: MenuWidget, base_widget: Widget) -> None:
self.screen_manager = cast(ScreenManager, self.ids.screen_manager)
self.slider = self.ids.slider

def clear_widget_subscriptions(self: MenuWidget) -> None:
def _clear_widget_subscriptions(self: MenuWidget) -> None:
"""Clear widget subscriptions."""
with self.widget_subscriptions_lock:
subscriptions = self.widget_subscriptions.copy()
self.widget_subscriptions.clear()
for subscription in subscriptions:
subscription()

def clear_screen_subscriptions(self: MenuWidget) -> None:
def _clear_screen_subscriptions(self: MenuWidget) -> None:
"""Clear screen subscriptions."""
# lock the mutex to do it atomic
with self.screen_subscriptions_lock:
Expand Down
7 changes: 7 additions & 0 deletions ubo_gui/menu/transitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from kivy.clock import mainthread
from kivy.uix.screenmanager import (
NoTransition,
RiseInTransition,
Screen,
ScreenManager,
SlideTransition,
Expand Down Expand Up @@ -100,6 +101,12 @@ def _slide_transition(self: TransitionsMixin) -> SlideTransition:
self._setup_transition(transition)
return transition

@cached_property
def _rise_in_transition(self: TransitionsMixin) -> RiseInTransition:
transition = RiseInTransition()
self._setup_transition(transition)
return transition

@cached_property
def _swap_transition(self: TransitionsMixin) -> SwapTransition:
transition = SwapTransition()
Expand Down
2 changes: 1 addition & 1 deletion ubo_gui/menu/widgets/item_widget.kv
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ItemWidget>:
orientation: 'horizontal'
height: dp(UBO_GUI_MENU_ITEM_HEIGHT)
opacity: root.opacity
opacity: root.opacity if root.is_set else 0

canvas.before:
Color:
Expand Down

0 comments on commit 9076fca

Please sign in to comment.