snakia/src/snakia/core/tui/widget.py

38 lines
1,008 B
Python

from abc import ABC, abstractmethod
from typing import Final, TypeVar, final
from snakia.core.rx import AsyncBindable, Bindable
from snakia.utils import to_async
from .canvas import Canvas
T = TypeVar("T")
class Widget(ABC):
def __init__(self) -> None:
self.dirty: Final = Bindable(True)
self.__cache: Canvas = Canvas(0, 0)
@abstractmethod
def on_render(self) -> Canvas: ...
@final
def render(self) -> Canvas:
if self.dirty.value:
result = self.on_render()
self.__cache = result
self.dirty.set(False)
return self.__cache
@final
def state(self, default_value: T) -> Bindable[T]:
field = Bindable(default_value)
field.subscribe(lambda _: self.dirty.set(True))
return field
@final
def async_state(self, default_value: T) -> AsyncBindable[T]:
field = AsyncBindable(default_value)
field.subscribe(to_async(lambda _: self.dirty.set(True)))
return field