135 lines
4.2 KiB
Python
135 lines
4.2 KiB
Python
from __future__ import annotations
|
|
|
|
import typing
|
|
import warnings
|
|
|
|
from urwid.canvas import CompositeCanvas
|
|
|
|
from .constants import Sizing
|
|
from .widget_decoration import WidgetDecoration, WidgetError
|
|
|
|
WrappedWidget = typing.TypeVar("WrappedWidget")
|
|
|
|
|
|
class BoxAdapterError(WidgetError):
|
|
pass
|
|
|
|
|
|
class BoxAdapter(WidgetDecoration[WrappedWidget]):
|
|
"""
|
|
Adapter for using a box widget where a flow widget would usually go
|
|
"""
|
|
|
|
no_cache: typing.ClassVar[list[str]] = ["rows"]
|
|
|
|
def __init__(self, box_widget: WrappedWidget, height: int) -> None:
|
|
"""
|
|
Create a flow widget that contains a box widget
|
|
|
|
:param box_widget: box widget to wrap
|
|
:type box_widget: Widget
|
|
:param height: number of rows for box widget
|
|
:type height: int
|
|
|
|
>>> from urwid import SolidFill
|
|
>>> BoxAdapter(SolidFill(u"x"), 5) # 5-rows of x's
|
|
<BoxAdapter flow widget <SolidFill box widget 'x'> height=5>
|
|
"""
|
|
if hasattr(box_widget, "sizing") and Sizing.BOX not in box_widget.sizing():
|
|
raise BoxAdapterError(f"{box_widget!r} is not a box widget")
|
|
super().__init__(box_widget)
|
|
|
|
self.height = height
|
|
|
|
def _repr_attrs(self) -> dict[str, typing.Any]:
|
|
return {**super()._repr_attrs(), "height": self.height}
|
|
|
|
# originally stored as box_widget, keep for compatibility
|
|
@property
|
|
def box_widget(self) -> WrappedWidget:
|
|
warnings.warn(
|
|
"original stored as original_widget, keep for compatibility",
|
|
PendingDeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
return self.original_widget
|
|
|
|
@box_widget.setter
|
|
def box_widget(self, widget: WrappedWidget) -> None:
|
|
warnings.warn(
|
|
"original stored as original_widget, keep for compatibility",
|
|
PendingDeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
self.original_widget = widget
|
|
|
|
def sizing(self) -> frozenset[Sizing]:
|
|
return frozenset((Sizing.FLOW,))
|
|
|
|
def rows(self, size: tuple[int], focus: bool = False) -> int:
|
|
"""
|
|
Return the predetermined height (behave like a flow widget)
|
|
|
|
>>> from urwid import SolidFill
|
|
>>> BoxAdapter(SolidFill(u"x"), 5).rows((20,))
|
|
5
|
|
"""
|
|
return self.height
|
|
|
|
# The next few functions simply tack-on our height and pass through
|
|
# to self._original_widget
|
|
def get_cursor_coords(self, size: tuple[int]) -> int | None:
|
|
(maxcol,) = size
|
|
if not hasattr(self._original_widget, "get_cursor_coords"):
|
|
return None
|
|
return self._original_widget.get_cursor_coords((maxcol, self.height))
|
|
|
|
def get_pref_col(self, size: tuple[int]) -> int | None:
|
|
(maxcol,) = size
|
|
if not hasattr(self._original_widget, "get_pref_col"):
|
|
return None
|
|
return self._original_widget.get_pref_col((maxcol, self.height))
|
|
|
|
def keypress(
|
|
self,
|
|
size: tuple[int], # type: ignore[override]
|
|
key: str,
|
|
) -> str | None:
|
|
(maxcol,) = size
|
|
return self._original_widget.keypress((maxcol, self.height), key)
|
|
|
|
def move_cursor_to_coords(self, size: tuple[int], col: int, row: int):
|
|
(maxcol,) = size
|
|
if not hasattr(self._original_widget, "move_cursor_to_coords"):
|
|
return True
|
|
return self._original_widget.move_cursor_to_coords((maxcol, self.height), col, row)
|
|
|
|
def mouse_event(
|
|
self,
|
|
size: tuple[int], # type: ignore[override]
|
|
event: str,
|
|
button: int,
|
|
col: int,
|
|
row: int,
|
|
focus: bool,
|
|
) -> bool | None:
|
|
(maxcol,) = size
|
|
if not hasattr(self._original_widget, "mouse_event"):
|
|
return False
|
|
return self._original_widget.mouse_event((maxcol, self.height), event, button, col, row, focus)
|
|
|
|
def render(
|
|
self,
|
|
size: tuple[int], # type: ignore[override]
|
|
focus: bool = False,
|
|
) -> CompositeCanvas:
|
|
(maxcol,) = size
|
|
canv = CompositeCanvas(self._original_widget.render((maxcol, self.height), focus))
|
|
return canv
|
|
|
|
def __getattr__(self, name: str):
|
|
"""
|
|
Pass calls to box widget.
|
|
"""
|
|
return getattr(self.original_widget, name)
|