pytermgui.widgets.button

This module contains the Button class.

  1"""This module contains the `Button` class."""
  2
  3
  4from __future__ import annotations
  5
  6from typing import Any, Callable, Optional
  7
  8from ..ansi_interface import MouseAction, MouseEvent
  9from ..input import keys
 10from ..regex import real_length
 11from . import styles as w_styles
 12from .base import Widget
 13
 14
 15class Button(Widget):
 16    """A simple Widget representing a mouse-clickable button"""
 17
 18    styles = w_styles.StyleManager(
 19        label=w_styles.CLICKABLE,
 20        highlight=w_styles.CLICKED,
 21        _current=None,
 22    )
 23
 24    chars: dict[str, w_styles.CharType] = {"delimiter": ["[ ", " ]"]}
 25
 26    def __init__(
 27        self,
 28        label: str = "Button",
 29        onclick: Optional[Callable[[Button], Any]] = None,
 30        padding: int = 0,
 31        centered: bool = False,
 32        **attrs: Any,
 33    ) -> None:
 34        """Initialize object"""
 35
 36        super().__init__(**attrs)
 37        self._selectables_length = 1
 38
 39        if not any("width" in attr for attr in attrs):
 40            self.width = len(label)
 41
 42        self.label = label
 43        self.onclick = onclick
 44        self.padding = padding
 45        self.centered = centered
 46
 47        self.styles["_current"] = self.styles.label
 48
 49    def on_hover(self, _) -> bool:
 50        """Sets highlight style when hovering."""
 51
 52        self.styles["_current"] = self.styles.highlight
 53        return False
 54
 55    def on_release(self, _) -> bool:
 56        """Sets normal style when no longer hovering."""
 57
 58        self.styles["_current"] = self.styles.label
 59        return False
 60
 61    def handle_mouse(self, event: MouseEvent) -> bool:
 62        """Handles a mouse event"""
 63
 64        if super().handle_mouse(event):
 65            return True
 66
 67        if event.action == MouseAction.LEFT_CLICK:
 68            self.selected_index = 0
 69            if self.onclick is not None:
 70                self.onclick(self)
 71
 72            return True
 73
 74        if event.action == MouseAction.RELEASE:
 75            self.selected_index = None
 76            return True
 77
 78        return False
 79
 80    def handle_key(self, key: str) -> bool:
 81        """Handles a keypress"""
 82
 83        if key == keys.RETURN and self.onclick is not None:
 84            self.onclick(self)
 85            return True
 86
 87        return False
 88
 89    def get_lines(self) -> list[str]:
 90        """Get object lines"""
 91
 92        delimiters = self._get_char("delimiter")
 93        assert isinstance(delimiters, list) and len(delimiters) == 2
 94
 95        left, right = delimiters
 96        left = left.replace("[", r"\[")
 97        delim_len = real_length(left + right)
 98
 99        label = self.label
100        if len(self.label) > self.width:
101            sli = max(self.width - delim_len - 3 - self.padding, 0)
102            label = self.label[:sli] + "..."
103
104        elif self.centered:
105            label = self.label.center(self.width)
106
107        if self.selected_index is None:
108            style = self.styles["_current"]
109        else:
110            style = self.styles.highlight
111
112        line = style(left + label + right + self.padding * " ")
113
114        return [line]
class Button(pytermgui.widgets.base.Widget):
 16class Button(Widget):
 17    """A simple Widget representing a mouse-clickable button"""
 18
 19    styles = w_styles.StyleManager(
 20        label=w_styles.CLICKABLE,
 21        highlight=w_styles.CLICKED,
 22        _current=None,
 23    )
 24
 25    chars: dict[str, w_styles.CharType] = {"delimiter": ["[ ", " ]"]}
 26
 27    def __init__(
 28        self,
 29        label: str = "Button",
 30        onclick: Optional[Callable[[Button], Any]] = None,
 31        padding: int = 0,
 32        centered: bool = False,
 33        **attrs: Any,
 34    ) -> None:
 35        """Initialize object"""
 36
 37        super().__init__(**attrs)
 38        self._selectables_length = 1
 39
 40        if not any("width" in attr for attr in attrs):
 41            self.width = len(label)
 42
 43        self.label = label
 44        self.onclick = onclick
 45        self.padding = padding
 46        self.centered = centered
 47
 48        self.styles["_current"] = self.styles.label
 49
 50    def on_hover(self, _) -> bool:
 51        """Sets highlight style when hovering."""
 52
 53        self.styles["_current"] = self.styles.highlight
 54        return False
 55
 56    def on_release(self, _) -> bool:
 57        """Sets normal style when no longer hovering."""
 58
 59        self.styles["_current"] = self.styles.label
 60        return False
 61
 62    def handle_mouse(self, event: MouseEvent) -> bool:
 63        """Handles a mouse event"""
 64
 65        if super().handle_mouse(event):
 66            return True
 67
 68        if event.action == MouseAction.LEFT_CLICK:
 69            self.selected_index = 0
 70            if self.onclick is not None:
 71                self.onclick(self)
 72
 73            return True
 74
 75        if event.action == MouseAction.RELEASE:
 76            self.selected_index = None
 77            return True
 78
 79        return False
 80
 81    def handle_key(self, key: str) -> bool:
 82        """Handles a keypress"""
 83
 84        if key == keys.RETURN and self.onclick is not None:
 85            self.onclick(self)
 86            return True
 87
 88        return False
 89
 90    def get_lines(self) -> list[str]:
 91        """Get object lines"""
 92
 93        delimiters = self._get_char("delimiter")
 94        assert isinstance(delimiters, list) and len(delimiters) == 2
 95
 96        left, right = delimiters
 97        left = left.replace("[", r"\[")
 98        delim_len = real_length(left + right)
 99
100        label = self.label
101        if len(self.label) > self.width:
102            sli = max(self.width - delim_len - 3 - self.padding, 0)
103            label = self.label[:sli] + "..."
104
105        elif self.centered:
106            label = self.label.center(self.width)
107
108        if self.selected_index is None:
109            style = self.styles["_current"]
110        else:
111            style = self.styles.highlight
112
113        line = style(left + label + right + self.padding * " ")
114
115        return [line]

A simple Widget representing a mouse-clickable button

Button( label: str = 'Button', onclick: Optional[Callable[[pytermgui.widgets.button.Button], Any]] = None, padding: int = 0, centered: bool = False, **attrs: Any)
27    def __init__(
28        self,
29        label: str = "Button",
30        onclick: Optional[Callable[[Button], Any]] = None,
31        padding: int = 0,
32        centered: bool = False,
33        **attrs: Any,
34    ) -> None:
35        """Initialize object"""
36
37        super().__init__(**attrs)
38        self._selectables_length = 1
39
40        if not any("width" in attr for attr in attrs):
41            self.width = len(label)
42
43        self.label = label
44        self.onclick = onclick
45        self.padding = padding
46        self.centered = centered
47
48        self.styles["_current"] = self.styles.label

Initialize object

styles = {'label': StyleCall(obj=None, method=MarkupFormatter(markup='[@238 72 bold]{item}', ensure_strip=False, _markup_cache={})), 'highlight': StyleCall(obj=None, method=MarkupFormatter(markup='[238 @72 bold]{item}', ensure_strip=False, _markup_cache={})), '_current': StyleCall(obj=None, method=None)}

Default styles for this class

chars: dict[str, typing.Union[typing.List[str], str]] = {'delimiter': ['[ ', ' ]']}

Default characters for this class

def on_hover(self, _) -> bool:
50    def on_hover(self, _) -> bool:
51        """Sets highlight style when hovering."""
52
53        self.styles["_current"] = self.styles.highlight
54        return False

Sets highlight style when hovering.

def on_release(self, _) -> bool:
56    def on_release(self, _) -> bool:
57        """Sets normal style when no longer hovering."""
58
59        self.styles["_current"] = self.styles.label
60        return False

Sets normal style when no longer hovering.

def handle_mouse(self, event: pytermgui.ansi_interface.MouseEvent) -> bool:
62    def handle_mouse(self, event: MouseEvent) -> bool:
63        """Handles a mouse event"""
64
65        if super().handle_mouse(event):
66            return True
67
68        if event.action == MouseAction.LEFT_CLICK:
69            self.selected_index = 0
70            if self.onclick is not None:
71                self.onclick(self)
72
73            return True
74
75        if event.action == MouseAction.RELEASE:
76            self.selected_index = None
77            return True
78
79        return False

Handles a mouse event

def handle_key(self, key: str) -> bool:
81    def handle_key(self, key: str) -> bool:
82        """Handles a keypress"""
83
84        if key == keys.RETURN and self.onclick is not None:
85            self.onclick(self)
86            return True
87
88        return False

Handles a keypress

def get_lines(self) -> list[str]:
 90    def get_lines(self) -> list[str]:
 91        """Get object lines"""
 92
 93        delimiters = self._get_char("delimiter")
 94        assert isinstance(delimiters, list) and len(delimiters) == 2
 95
 96        left, right = delimiters
 97        left = left.replace("[", r"\[")
 98        delim_len = real_length(left + right)
 99
100        label = self.label
101        if len(self.label) > self.width:
102            sli = max(self.width - delim_len - 3 - self.padding, 0)
103            label = self.label[:sli] + "..."
104
105        elif self.centered:
106            label = self.label.center(self.width)
107
108        if self.selected_index is None:
109            style = self.styles["_current"]
110        else:
111            style = self.styles.highlight
112
113        line = style(left + label + right + self.padding * " ")
114
115        return [line]

Get object lines