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/widgets/demo.png"
 55  width=100%>
 56</p>
 57"""
 58
 59from __future__ import annotations
 60
 61from typing import Optional, Union, Type
 62
 63from . import boxes
 64
 65from .base import *
 66from .styles import *
 67from .containers import *
 68from .interactive import *
 69from .collapsible import *
 70from .pixel_matrix import *
 71from .color_picker import ColorPicker
 72
 73WidgetType = Union[Widget, Type[Widget]]
 74
 75
 76class _IDManager:
 77    """Simple object to store all widgets in a program, and
 78    allow referencing by id."""
 79
 80    def __init__(self) -> None:
 81        """Initialize dict"""
 82
 83        self._widgets: dict[str, WidgetType] = {}
 84
 85    def register(self, other: Widget) -> None:
 86        """Add widget to self._widgets
 87
 88        This method is meant to be called only internally by Widget."""
 89
 90        objid = other.id
 91
 92        if objid is None:
 93            raise ValueError("Cannot register element with no ID!")
 94
 95        self._widgets[objid] = other
 96
 97    def deregister(self, key: str) -> None:
 98        """Remove widget from self._widgets
 99
100        This method is meant to be called only internally by Widget."""
101
102        del self._widgets[key]
103
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
112
113    def get_widget(self, widget_id: str) -> Optional[WidgetType]:
114        """Get widget by id"""
115
116        return self._widgets.get(widget_id)
117
118
119_manager = _IDManager()
120setattr(Widget, "_id_manager", _manager)
121
122get_widget = _manager.get_widget
123get_id = _manager.get_id
def get_widget( widget_id: str) -> Union[pytermgui.widgets.base.Widget, Type[pytermgui.widgets.base.Widget], NoneType]:
114    def get_widget(self, widget_id: str) -> Optional[WidgetType]:
115        """Get widget by id"""
116
117        return self._widgets.get(widget_id)

Get widget by id

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

Check if a widget has been registered