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()

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

Get widget by id

def get_id(other: pytermgui.widgets.base.Widget) -> Optional[str]:
108    def get_id(self, other: Widget) -> Optional[str]:
109        """Check if a widget has been registered"""
110
111        for key, widget in self._widgets.items():
112            if widget == other:
113                return key
114
115        return None

Check if a widget has been registered