Skip to content
Snippets Groups Projects

Refactor Cart into checkerboard table

Merged Mateusz Kudela requested to merge mkudela/issue-173 into develop
Compare and Show latest version
2 files
+ 37
5
Compare changes
  • Side-by-side
  • Inline
Files
2
from __future__ import annotations
import contextlib
from typing import TYPE_CHECKING
from textual import on
from textual.binding import Binding
from textual.containers import Horizontal
from textual.css.query import NoMatches
from textual.message import Message
from textual.widgets import Static
@@ -25,6 +27,7 @@ from clive.__private.ui.widgets.scrolling import ScrollablePart
if TYPE_CHECKING:
from textual.app import ComposeResult
from typing_extensions import Self
from clive.models import Operation
@@ -69,6 +72,13 @@ class CartItem(CliveCheckerboardTableRow, CliveWidget):
self.to_idx = to_idx
super().__init__()
class Focus(Message):
"""Message sent when other CartItem should be focused."""
def __init__(self, target_idx: int) -> None:
self.target_idx = target_idx
super().__init__()
def __init__(self, operation_idx: int) -> None:
self.__idx = operation_idx
assert self.is_valid(), "During construction, index has to be valid"
@@ -96,12 +106,32 @@ class CartItem(CliveCheckerboardTableRow, CliveWidget):
def is_valid(self) -> bool:
return self.__idx < self.__operations_count
def focus(self, _: bool = True) -> Self:
if focused := self.app.focused: # Focus the corresponding button as it was before
assert focused.id, "Previously focused widget has no id!"
with contextlib.suppress(NoMatches):
previous = self.get_child_by_id(focused.id)
if previous.focusable:
previous.focus()
return self
for child in reversed(self.children): # Focus first focusable
if child.focusable:
child.focus()
return self
def get_operation_index(self) -> str:
return f"{self.__idx + 1}." if self.is_valid() else "?"
def get_operation_name(self) -> str:
return humanize_operation_name(self.operation) if self.is_valid() else "?"
def action_select_previous(self) -> None:
self.post_message(self.Focus(target_idx=self.__idx - 1))
def action_select_next(self) -> None:
self.post_message(self.Focus(target_idx=self.__idx + 1))
def get_operation_details(self) -> str:
return humanize_operation_details(self.operation) if self.is_valid() else "?"
@@ -188,8 +218,10 @@ class Cart(BaseScreen):
with self.__scrollable_part:
yield CartTable()
async def __rebuild_items(self, from_index: int = 0) -> None:
await self.query_one(CartTable).rebuild(starting_from_element=from_index, row_type=CartItem)
async def __rebuild_items(self, from_index: int = 0, to_index: int | None = None) -> None:
await self.query_one(CartTable).rebuild(
starting_from_element=from_index, ending_with_element=to_index, row_type=CartItem
)
@on(CartItem.Delete)
async def remove_item(self, event: CartItem.Delete) -> None:
@@ -205,7 +237,7 @@ class Cart(BaseScreen):
self.app.world.profile_data.cart.swap(event.from_idx, event.to_idx)
self.app.trigger_profile_data_watchers()
start, end = (event.from_idx, event.to_idx) if event.from_idx < event.to_idx else (event.to_idx, event.from_idx)
await self.query_one(CartTable).rebuild(starting_from_element=start, ending_with_element=end, row_type=CartItem)
await self.__rebuild_items(from_index=start, to_index=end)
def action_summary(self) -> None:
self.app.push_screen(TransactionSummaryFromCart())
Loading