pytermgui.widgets

The widget system.

Basic concept

Everything starts with the Widget class. It represents a single part of the overarching system. Simple widgets like Label simply implement a get_lines method, in which they can come up with what to display as.

The more complex type widget is something like Container. This widget holds other widgets within itself, and uses some fancy logic to display them in a neat and organized way.

Magic methods

Most widgets support a selection of magic methods, also known as dunders. For example, all Container children are iterable by default, and allow adding elements using the += operator. You can also index into them, if that floats your boat.

Demo

There is a lot more information specific to each widget, located in its documentation. For now, here is a cool showcase of this part of pytermgui.

import sys
import pytermgui as ptg

with ptg.alt_buffer():
    root = ptg.Container(
        ptg.Label("[210 bold]This is a title"),
        ptg.Label(""),
        ptg.Label("[italic grey]This is some body text. It is very interesting."),
        ptg.Label(),
        ptg.Button("[red]Stop application!", onclick=lambda *_: sys.exit()),
        ptg.Button("[green]Do nothing"),
    )

    root.center().print()

    while True:
        root.handle_key(ptg.getch())
        root.print()

View Source
  0"""
  1The widget system.
  2
  3Basic concept
  4-------------
  5
  6Everything starts with the `Widget` class. It represents a single part
  7of the overarching system. Simple widgets like `Label` simply implement
  8a `get_lines` method, in which they can come up with what to display as.
  9
 10The more complex type widget is something like `Container`. This widget holds
 11other widgets within itself, and uses some fancy logic to display them
 12in a neat and organized way.
 13
 14
 15Magic methods
 16-------------
 17
 18Most widgets support a selection of magic methods, also known as dunders.
 19For example, all `Container` children are iterable by default, and allow
 20adding elements using the `+=` operator. You can also index into them, if
 21that floats your boat.
 22
 23
 24Demo
 25----
 26
 27There is a lot more information specific to each widget, located in its
 28documentation. For now, here is a cool showcase of this part of pytermgui.
 29
 30```python3
 31import sys
 32import pytermgui as ptg
 33
 34with ptg.alt_buffer():
 35    root = ptg.Container(
 36        ptg.Label("[210 bold]This is a title"),
 37        ptg.Label(""),
 38        ptg.Label("[italic grey]This is some body text. It is very interesting."),
 39        ptg.Label(),
 40        ptg.Button("[red]Stop application!", onclick=lambda *_: sys.exit()),
 41        ptg.Button("[green]Do nothing"),
 42    )
 43
 44    root.center().print()
 45
 46    while True:
 47        root.handle_key(ptg.getch())
 48        root.print()
 49```
 50
 51<p style="text-align: center">
 52 <img
 53  src="https://raw.githubusercontent.com/bczsalba/pytermgui/master/assets/docs/widgets/demo.png"
 54  width=100%>
 55</p>
 56"""
 57
 58from __future__ import annotations
 59
 60from typing import Optional, Union, Type
 61
 62from . import boxes
 63
 64from .base import *
 65from .styles import *
 66from .containers import *
 67from .interactive import *
 68from .collapsible import *
 69from .pixel_matrix import *
 70from .color_picker import ColorPicker
 71
 72WidgetType = Union[Widget, Type[Widget]]
 73
 74
 75class _IDManager:
 76    """Simple object to store all widgets in a program, and
 77    allow referencing by id."""
 78
 79    def __init__(self) -> None:
 80        """Initialize dict"""
 81
 82        self._widgets: dict[str, WidgetType] = {}
 83
 84    def register(self, other: Widget) -> None:
 85        """Add widget to self._widgets
 86
 87        This method is meant to be called only internally by Widget."""
 88
 89        objid = other.id
 90
 91        if objid is None:
 92            raise ValueError("Cannot register element with no ID!")
 93
 94        self._widgets[objid] = other
 95
 96    def deregister(self, key: str) -> None:
 97        """Remove widget from self._widgets
 98
 99        This method is meant to be called only internally by Widget."""
100
101        del self._widgets[key]
102
103    def get_id(self, other: Widget) -> Optional[str]:
104        """Check if a widget has been registered"""
105
106        for key, widget in self._widgets.items():
107            if widget == other:
108                return key
109
110        return None
111
112    def get_widget(self, widget_id: str) -> Optional[WidgetType]:
113        """Get widget by id"""
114
115        return self._widgets.get(widget_id)
116
117
118_manager = _IDManager()
119setattr(Widget, "_id_manager", _manager)
120
121get_widget = _manager.get_widget
122get_id = _manager.get_id
#   def get_widget( widget_id: str ) -> Union[pytermgui.widgets.base.Widget, Type[pytermgui.widgets.base.Widget], NoneType]:
View Source
113    def get_widget(self, widget_id: str) -> Optional[WidgetType]:
114        """Get widget by id"""
115
116        return self._widgets.get(widget_id)

Get widget by id

#   def get_id(other: pytermgui.widgets.base.Widget) -> Optional[str]:
View Source
104    def get_id(self, other: Widget) -> Optional[str]:
105        """Check if a widget has been registered"""
106
107        for key, widget in self._widgets.items():
108            if widget == other:
109                return key
110
111        return None

Check if a widget has been registered