Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
widget_decoration.py142 linesDownload Raw Back to widget
1from __future__ import annotations2 3import typing4import warnings5 6from urwid.canvas import CompositeCanvas7 8from .widget import Widget, WidgetError, WidgetWarning, delegate_to_widget_mixin9 10if typing.TYPE_CHECKING:11    from typing_extensions import Literal12 13    from .constants import Sizing14 15 16__all__ = (17    "WidgetDecoration",18    "WidgetDisable",19    "WidgetError",20    "WidgetPlaceholder",21    "WidgetWarning",22    "delegate_to_widget_mixin",23)24 25WrappedWidget = typing.TypeVar("WrappedWidget")26 27 28class WidgetDecoration(Widget, typing.Generic[WrappedWidget]):  # pylint: disable=abstract-method29    """30    original_widget -- the widget being decorated31 32    This is a base class for decoration widgets,33    widgets that contain one or more widgets and only ever have a single focus.34    This type of widget will affect the display or behaviour of the original_widget,35    but it is not part of determining a chain of focus.36 37    Don't actually do this -- use a WidgetDecoration subclass instead, these are not real widgets:38 39    >>> from urwid import Text40    >>> WidgetDecoration(Text("hi"))41    <WidgetDecoration fixed/flow widget <Text fixed/flow widget 'hi'>>42 43    .. Warning:44        WidgetDecoration do not implement ``render`` method.45        Implement it or forward to the widget in the subclass.46    """47 48    def __init__(self, original_widget: WrappedWidget) -> None:49        # TODO(Aleksei): reduce amount of multiple inheritance usage50        # Special case: subclasses with multiple inheritance causes `super` call wrong way51        # Call parent __init__ explicit52        Widget.__init__(self)53        if not isinstance(original_widget, Widget):54            obj_class_path = f"{original_widget.__class__.__module__}.{original_widget.__class__.__name__}"55            warnings.warn(56                f"{obj_class_path} is not subclass of Widget",57                DeprecationWarning,58                stacklevel=2,59            )60        self._original_widget = original_widget61 62    def _repr_words(self) -> list[str]:63        return [*super()._repr_words(), repr(self._original_widget)]64 65    @property66    def original_widget(self) -> WrappedWidget:67        return self._original_widget68 69    @original_widget.setter70    def original_widget(self, original_widget: WrappedWidget) -> None:71        self._original_widget = original_widget72        self._invalidate()73 74    @property75    def base_widget(self) -> Widget:76        """77        Return the widget without decorations.78 79        If there is only one Decoration, then this is the same as original_widget.80 81        >>> from urwid import Text82        >>> t = Text("hello")83        >>> wd1 = WidgetDecoration(t)84        >>> wd2 = WidgetDecoration(wd1)85        >>> wd3 = WidgetDecoration(wd2)86        >>> wd3.original_widget is wd287        True88        >>> wd3.base_widget is t89        True90        """91        visited = {self}92        w = self93        while (w := getattr(w, "_original_widget", w)) not in visited:94            visited.add(w)95        return w96 97    def selectable(self) -> bool:98        return self._original_widget.selectable()99 100    def sizing(self) -> frozenset[Sizing]:101        return self._original_widget.sizing()102 103 104class WidgetPlaceholder(delegate_to_widget_mixin("_original_widget"), WidgetDecoration[WrappedWidget]):105    """106    This is a do-nothing decoration widget that can be used for swapping107    between widgets without modifying the container of this widget.108 109    This can be useful for making an interface with a number of distinct110    pages or for showing and hiding menu or status bars.111 112    The widget displayed is stored as the self.original_widget property and113    can be changed by assigning a new widget to it.114    """115 116 117class WidgetDisable(WidgetDecoration[WrappedWidget]):118    """119    A decoration widget that disables interaction with the widget it120    wraps.  This widget always passes focus=False to the wrapped widget,121    even if it somehow does become the focus.122    """123 124    no_cache: typing.ClassVar[list[str]] = ["rows"]125    ignore_focus = True126 127    def selectable(self) -> Literal[False]:128        return False129 130    def rows(self, size: tuple[int], focus: bool = False) -> int:131        return self._original_widget.rows(size, False)132 133    def sizing(self) -> frozenset[Sizing]:134        return self._original_widget.sizing()135 136    def pack(self, size, focus: bool = False) -> tuple[int, int]:137        return self._original_widget.pack(size, False)138 139    def render(self, size, focus: bool = False) -> CompositeCanvas:140        canv = self._original_widget.render(size, False)141        return CompositeCanvas(canv)142 
codekingpro/portable-devtools · Team Ai