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

Sets highlight style when hovering.

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

Sets normal style when no longer hovering.

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

Handles a mouse event

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

Handles a keypress

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

Get object lines