From e0ac60ce03d7c54855abf850f2d477b971a55ca6 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 11 May 2023 16:19:13 +0100 Subject: [PATCH] Initial framework for the SelectionList Nothing here actually implements a selection list yet; this just sets out the very basic framework of the widget, as it inherits form OptionList. The key things here are: 1. It introduces a Selection class, which is an Option with a typed value. 2. The SelectionList is also typed and expects Selections of that type. --- src/textual/widgets/__init__.py | 2 + src/textual/widgets/__init__.pyi | 1 + src/textual/widgets/_selection_list.py | 57 ++++++++++++++++++++++++++ src/textual/widgets/selection_list.py | 3 ++ 4 files changed, 63 insertions(+) create mode 100644 src/textual/widgets/_selection_list.py create mode 100644 src/textual/widgets/selection_list.py diff --git a/src/textual/widgets/__init__.py b/src/textual/widgets/__init__.py index 04e00e53b..3ed23b4c2 100644 --- a/src/textual/widgets/__init__.py +++ b/src/textual/widgets/__init__.py @@ -30,6 +30,7 @@ if typing.TYPE_CHECKING: from ._radio_button import RadioButton from ._radio_set import RadioSet from ._select import Select + from ._selection_list import SelectionList from ._static import Static from ._switch import Switch from ._tabbed_content import TabbedContent, TabPane @@ -61,6 +62,7 @@ __all__ = [ "RadioButton", "RadioSet", "Select", + "SelectionList", "Static", "Switch", "Tab", diff --git a/src/textual/widgets/__init__.pyi b/src/textual/widgets/__init__.pyi index 27e7f4ed1..86a3985a5 100644 --- a/src/textual/widgets/__init__.pyi +++ b/src/textual/widgets/__init__.pyi @@ -20,6 +20,7 @@ from ._progress_bar import ProgressBar as ProgressBar from ._radio_button import RadioButton as RadioButton from ._radio_set import RadioSet as RadioSet from ._select import Select as Select +from ._selection_list import SelectionList as SelectionList from ._static import Static as Static from ._switch import Switch as Switch from ._tabbed_content import TabbedContent as TabbedContent diff --git a/src/textual/widgets/_selection_list.py b/src/textual/widgets/_selection_list.py new file mode 100644 index 000000000..4f1259b73 --- /dev/null +++ b/src/textual/widgets/_selection_list.py @@ -0,0 +1,57 @@ +"""Provides a selection list widget, allowing one or more items to be selected.""" + +from typing import Generic, TypeVar + +from rich.console import RenderableType + +from ._option_list import Option, OptionList + +SelectionType = TypeVar("SelectionType") +"""The type for the value of a `Selection`""" + + +class Selection(Generic[SelectionType], Option): + """A selection for the `SelectionList`.""" + + def __init__( + self, + value: SelectionType, + prompt: RenderableType, + id: str | None = None, + disabled: bool = False, + ): + """Initialise the selection. + + Args: + value: The value for the selection. + prompt: The prompt for the selection. + id: The optional ID for the selection. + disabled: The initial enabled/disabled state. Enabled by default. + """ + super().__init__(prompt, id, disabled) + self._value: SelectionType = value + + +class SelectionList(Generic[SelectionType], OptionList): + """A vertical option list that allows making multiple selections.""" + + def __init__( + self, + *selections: Selection[SelectionType], + name: str | None = None, + id: str | None = None, + classes: str | None = None, + disabled: bool = False, + ): + """Initialise the selection list. + + Args: + *content: The content for the selection list. + name: The name of the selection list. + id: The ID of the selection list in the DOM. + classes: The CSS classes of the selection list. + disabled: Whether the selection list is disabled or not. + """ + super().__init__( + *selections, name=name, id=id, classes=classes, disabled=disabled + ) diff --git a/src/textual/widgets/selection_list.py b/src/textual/widgets/selection_list.py new file mode 100644 index 000000000..3f87209cb --- /dev/null +++ b/src/textual/widgets/selection_list.py @@ -0,0 +1,3 @@ +from ._selection_list import Selection + +__all__ = ["Selection"]