Initial planning of the class hierarchy for toggle widgets

This commit is contained in:
Dave Pearson
2023-02-15 17:09:33 +00:00
parent 56b0214c6b
commit 6982805922
5 changed files with 123 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ from ..case import camel_to_snake
if typing.TYPE_CHECKING:
from ..widget import Widget
from ._button import Button
from ._checkbox import Checkbox
from ._data_table import DataTable
from ._directory_tree import DirectoryTree
from ._footer import Footer
@@ -22,6 +23,7 @@ if typing.TYPE_CHECKING:
from ._markdown import Markdown, MarkdownViewer
from ._placeholder import Placeholder
from ._pretty import Pretty
from ._radio_button import RadioButton
from ._static import Static
from ._switch import Switch
from ._text_log import TextLog
@@ -31,6 +33,7 @@ if typing.TYPE_CHECKING:
__all__ = [
"Button",
"Checkbox",
"DataTable",
"DirectoryTree",
"Footer",
@@ -43,6 +46,7 @@ __all__ = [
"MarkdownViewer",
"Placeholder",
"Pretty",
"RadioButton",
"Static",
"Switch",
"TextLog",

View File

@@ -1,5 +1,6 @@
# This stub file must re-export every classes exposed in the __init__.py's `__all__` list:
from ._button import Button as Button
from ._checkbox import Checkbox as Checkbox
from ._data_table import DataTable as DataTable
from ._directory_tree import DirectoryTree as DirectoryTree
from ._footer import Footer as Footer
@@ -12,6 +13,7 @@ from ._markdown import Markdown as Markdown
from ._markdown import MarkdownViewer as MarkdownViewer
from ._placeholder import Placeholder as Placeholder
from ._pretty import Pretty as Pretty
from ._radio_button import RadioButton as RadioButton
from ._static import Static as Static
from ._switch import Switch as Switch
from ._text_log import TextLog as TextLog

View File

@@ -0,0 +1,3 @@
from ._toggle import Checkbox
__all__ = ["Checkbox"]

View File

@@ -0,0 +1,3 @@
from ._toggle import RadioButton
__all__ = ["RadioButton"]

View File

@@ -0,0 +1,111 @@
"""Provides the base code and implementations of toggle widgets.
In particular it provides `Checkbox`, `RadioButton` and `RadioSet`.
"""
from __future__ import annotations
from rich.console import RenderableType
from ..app import RenderResult
from ..binding import Binding
from ..reactive import reactive
from ._static import Static
class ToggleButton(Static):
"""Base toggle button widget."""
BINDINGS: ClassVar[list[BindingType]] = [
Binding("enter,space", "toggle", "Toggle", show=False),
]
"""
| Key(s) | Description |
| :- | :- |
| enter,space | Toggle the value. |
"""
button_prefix: reactive[RenderableType] = reactive[RenderableType]("[")
"""The character for the left side of the toggle button."""
button_suffix: reactive[RenderableType] = reactive[RenderableType]("]")
"""The character for the right side of the toggle button."""
button_off: reactive[RenderableType] = reactive[RenderableType](" ")
"""The character used to signify that the button is off."""
button_on: reactive[RenderableType] = reactive[RenderableType]("X")
"""The character used to signify that the button is on."""
label: reactive[RenderableType] = reactive[RenderableType]("")
"""The label that describes the toggle."""
value: reactive[bool] = reactive(False)
"""The value of the button. `True` for on, `False` for off."""
def __init__(
self,
label: str,
value: bool = False,
*,
name: str | None = None,
id: str | None = None,
classes: str | None = None,
):
"""Initialise the toggle.
Args:
value: The initial value of the toggle. Defaults to `False`.
name: The name of the toggle.
id: The ID of the toggle in the DOM.
classes: The CSS classes of the toggle.
"""
super().__init__(name=name, id=id, classes=classes)
self.label = label
self.value = value
def render(self) -> RenderResult:
"""Render the content of the widget."""
# TODO: Built a renderable properly.
return (
f"{self.button_prefix}{self.button_on if self.value else self.button_off}{self.button_suffix}"
+ (" " if self.label else "")
+ f"{self.label}"
)
def action_toggle(self) -> None:
"""Toggle the value of the widget."""
self.value = not self.value
def on_click(self) -> None:
"""Toggle the value of the widget."""
self.action_toggle()
class Checkbox(ToggleButton):
pass
class RadioButton(ToggleButton):
def __init__(
self,
label: str,
value: bool = False,
*,
name: str | None = None,
id: str | None = None,
classes: str | None = None,
):
"""Initialise the radio button.
Args:
value: The initial value of the radio button. Defaults to `False`.
name: The name of the radio button.
id: The ID of the radio button in the DOM.
classes: The CSS classes of the radio button.
"""
super().__init__(label, value, name=name, id=id, classes=classes)
self.button_prefix = "("
self.button_suffix = ")"
self.button_on = "*"
self.button_off = " "