mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
api docs (#2240)
* api docs * more docstrings * logs * docs shakeup * fix notes, added intro to all apis * Remove defaults to * add note to events * note * use fira code
This commit is contained in:
15
docs/_templates/python/material/_base/class.html
vendored
15
docs/_templates/python/material/_base/class.html
vendored
@@ -13,7 +13,9 @@
|
|||||||
{% set show_full_path = config.show_object_full_path %}
|
{% set show_full_path = config.show_object_full_path %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if not root or config.show_root_heading %}
|
|
||||||
|
|
||||||
|
{% if 1 %}
|
||||||
|
|
||||||
{% filter heading(heading_level,
|
{% filter heading(heading_level,
|
||||||
role="class",
|
role="class",
|
||||||
@@ -34,7 +36,7 @@
|
|||||||
<code>{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}</code>
|
<code>{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}</code>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% with labels = class.labels %}
|
{% with labels = ['class'] %}
|
||||||
{% include "labels.html" with context %}
|
{% include "labels.html" with context %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
@@ -43,11 +45,10 @@
|
|||||||
{% if config.separate_signature and config.merge_init_into_class %}
|
{% if config.separate_signature and config.merge_init_into_class %}
|
||||||
{% if "__init__" in class.members %}
|
{% if "__init__" in class.members %}
|
||||||
{% with function = class.members["__init__"] %}
|
{% with function = class.members["__init__"] %}
|
||||||
{% filter highlight(language="python", inline=False) %}
|
{% filter highlight(language="python", inline=False) -%}
|
||||||
class {% filter format_signature(config.line_length) %}
|
def {% filter format_signature(config.line_length) %}
|
||||||
{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}
|
__init__{% include "signature.html" with context %}
|
||||||
{% include "signature.html" with context %}
|
{% endfilter %}:
|
||||||
{% endfilter %}
|
|
||||||
{% endfilter %}
|
{% endfilter %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
5
docs/_templates/python/material/_base/docstring/admonition.html
vendored
Normal file
5
docs/_templates/python/material/_base/docstring/admonition.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{{ log.debug("Rendering admonition") }}
|
||||||
|
<details class="{{ section.value.kind }}" open>
|
||||||
|
<summary>{{ section.title|convert_markdown(heading_level, html_id, strip_paragraph=True) }}</summary>
|
||||||
|
{{ section.value.contents|convert_markdown(heading_level, html_id) }}
|
||||||
|
</details>
|
||||||
@@ -29,8 +29,7 @@
|
|||||||
{% include "signature.html" with context %}
|
{% include "signature.html" with context %}
|
||||||
{% endfilter %}
|
{% endfilter %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% with labels = function.labels or [(function.parameters._parameters_list and function.parameters._parameters_list[0].name == 'self') and 'method' or 'function'] %}
|
||||||
{% with labels = function.labels %}
|
|
||||||
{% include "labels.html" with context %}
|
{% include "labels.html" with context %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
@@ -41,7 +40,7 @@
|
|||||||
def {% filter format_signature(config.line_length) %}
|
def {% filter format_signature(config.line_length) %}
|
||||||
{% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %}
|
{% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %}
|
||||||
{% include "signature.html" with context %}
|
{% include "signature.html" with context %}
|
||||||
{% endfilter %}
|
{% endfilter %}:
|
||||||
{% endfilter %}
|
{% endfilter %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
(
|
(
|
||||||
{%- for parameter in function.parameters -%}
|
{%- for parameter in function.parameters -%}
|
||||||
{%- if parameter.name not in ("self", "cls") or loop.index0 > 0 or not (function.parent and function.parent.is_class) -%}
|
{%- if 1 -%}
|
||||||
|
|
||||||
{%- if parameter.kind.value == "positional-only" -%}
|
{%- if parameter.kind.value == "positional-only" -%}
|
||||||
{%- set ns.has_pos_only = True -%}
|
{%- set ns.has_pos_only = True -%}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
::: textual.widgets.Button
|
|
||||||
::: textual.widgets._button.ButtonVariant
|
|
||||||
::: textual.widgets._button.InvalidButtonVariant
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.Checkbox
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.DataTable
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.DirectoryTree
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.Footer
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.Header
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.Input
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.Label
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.ListItem
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.ListView
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.LoadingIndicator
|
|
||||||
1
docs/api/logger.md
Normal file
1
docs/api/logger.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
::: textual.Logger
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.Markdown
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.MarkdownViewer
|
|
||||||
@@ -1,5 +1 @@
|
|||||||
A message pump is a class that processes messages.
|
|
||||||
|
|
||||||
It is a base class for the `App`, `Screen`, and `Widget` classes.
|
|
||||||
|
|
||||||
::: textual.message_pump
|
::: textual.message_pump
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
::: textual.widgets.OptionList
|
|
||||||
::: textual.widgets._option_list.Option
|
|
||||||
::: textual.widgets._option_list.Separator
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
::: textual.widgets.Placeholder
|
|
||||||
::: textual.widgets._placeholder.PlaceholderVariant
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.RadioButton
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.RadioSet
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.Static
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.Switch
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
::: textual.widgets.TabbedContent
|
|
||||||
::: textual.widgets.TabPane
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
::: textual.widgets.Tab
|
|
||||||
::: textual.widgets.Tabs
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.TextLog
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets._toggle_button.ToggleButton
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
::: textual.widgets.Tree
|
|
||||||
::: textual.widgets._tree.TreeNode
|
|
||||||
::: textual.widgets._tree.NodeID
|
|
||||||
::: textual.widgets._tree.TreeDataType
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
::: textual.widgets.Welcome
|
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
|
||||||
::: textual.work
|
::: textual.work
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Additionally there are new [update_cell][textual.widgets.DataTable.update_cell]
|
|||||||
|
|
||||||
## Tree control
|
## Tree control
|
||||||
|
|
||||||
The [Tree](../../api/tree.md) widget has grown a few methods to programmatically expand, collapse and toggle tree nodes.
|
The [Tree](../../widgets/tree.md) widget has grown a few methods to programmatically expand, collapse and toggle tree nodes.
|
||||||
|
|
||||||
## Breaking changes
|
## Breaking changes
|
||||||
|
|
||||||
|
|||||||
@@ -43,9 +43,14 @@ body[data-md-color-primary="black"] .excalidraw svg rect {
|
|||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.doc-object code {
|
||||||
|
font-family: "Fira Code", "SFMono-Regular", Consolas, "Courier New", Courier,
|
||||||
|
monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Indentation. */
|
/* Indentation. */
|
||||||
div.doc-contents:not(.first) .doc-contents {
|
div.doc-contents:not(.first) {
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
border-left: .05rem solid var(--md-typeset-table-color);
|
border-left: .05rem solid var(--md-typeset-table-color);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,13 @@ The WIDGET widget provides the following component classes:
|
|||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [WIDGET](../api/WIDGET.md) code reference.
|
|
||||||
- Another related API.
|
- Another related API.
|
||||||
- Something else useful.
|
- Something else useful.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.WIDGET
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -39,12 +39,15 @@ Clicking any of the non-disabled buttons in the example app below will result in
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.Button.Pressed
|
- [Button.Pressed][textual.widgets.Button.Pressed]
|
||||||
|
|
||||||
## Additional Notes
|
## Additional Notes
|
||||||
|
|
||||||
* The spacing between the text and the edges of a button are due to border, _not_ padding. To create a button with zero visible padding, use the `border: none;` declaration.
|
* The spacing between the text and the edges of a button are due to border, _not_ padding. To create a button with zero visible padding, use the `border: none;` declaration.
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [Button](../api/button.md) code reference
|
|
||||||
|
::: textual.widgets.Button
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -54,8 +54,12 @@ The checkbox widget provides the following component classes:
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.Checkbox.Changed
|
- [Checkbox.Changed][textual.widgets.Checkbox.Changed]
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
- [Checkbox](../api/checkbox.md) code reference
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.Checkbox
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -47,10 +47,13 @@ When the user presses the "Markdown" button the view is switched:
|
|||||||
## Reactive Attributes
|
## Reactive Attributes
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|-----------|-----------------|---------|----------------------------------------------------------------------|
|
| --------- | --------------- | ------- | ----------------------------------------------------------------------- |
|
||||||
| `current` | `str` \| `None` | `None` | The ID of the currently-visible child. `None` means nothing is visible. |
|
| `current` | `str` \| `None` | `None` | The ID of the currently-visible child. `None` means nothing is visible. |
|
||||||
|
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [ContentSwitcher][textual.widgets.ContentSwitcher] code reference
|
|
||||||
|
::: textual.widgets.ContentSwitcher
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -36,19 +36,13 @@ The example below populates a table with CSV data.
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.DataTable.CellHighlighted
|
- [DataTable.CellHighlighted][textual.widgets.DataTable.CellHighlighted]
|
||||||
|
- [DataTable.CellSelected][textual.widgets.DataTable.CellSelected]
|
||||||
### ::: textual.widgets.DataTable.CellSelected
|
- [DataTable.RowHighlighted][textual.widgets.DataTable.RowHighlighted]
|
||||||
|
- [DataTable.RowSelected][textual.widgets.DataTable.RowSelected]
|
||||||
### ::: textual.widgets.DataTable.RowHighlighted
|
- [DataTable.ColumnHighlighted][textual.widgets.DataTable.ColumnHighlighted]
|
||||||
|
- [DataTable.ColumnSelected][textual.widgets.DataTable.ColumnSelected]
|
||||||
### ::: textual.widgets.DataTable.RowSelected
|
- [DataTable.HeaderSelected][textual.widgets.DataTable.HeaderSelected]
|
||||||
|
|
||||||
### ::: textual.widgets.DataTable.ColumnHighlighted
|
|
||||||
|
|
||||||
### ::: textual.widgets.DataTable.ColumnSelected
|
|
||||||
|
|
||||||
### ::: textual.widgets.DataTable.HeaderSelected
|
|
||||||
|
|
||||||
## Bindings
|
## Bindings
|
||||||
|
|
||||||
@@ -68,6 +62,9 @@ The data table widget provides the following component classes:
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
show_root_toc_entry: false
|
show_root_toc_entry: false
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [DataTable][textual.widgets.DataTable] code reference
|
|
||||||
|
::: textual.widgets.DataTable
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ and directories:
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.DirectoryTree.FileSelected
|
- [DirectoryTree.FileSelected][textual.widgets.DirectoryTree.FileSelected]
|
||||||
|
|
||||||
## Reactive Attributes
|
## Reactive Attributes
|
||||||
|
|
||||||
@@ -57,5 +57,13 @@ The directory tree widget provides the following component classes:
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
* [DirectoryTree][textual.widgets.DirectoryTree] code reference
|
|
||||||
* [Tree][textual.widgets.Tree] code reference
|
* [Tree][textual.widgets.Tree] code reference
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.DirectoryTree
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ The footer widget provides the following component classes:
|
|||||||
* You can prevent keybindings from appearing in the footer by setting the `show` argument of the `Binding` to `False`.
|
* You can prevent keybindings from appearing in the footer by setting the `show` argument of the `Binding` to `False`.
|
||||||
* You can customize the text that appears for the key itself in the footer using the `key_display` argument of `Binding`.
|
* You can customize the text that appears for the key itself in the footer using the `key_display` argument of `Binding`.
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
* [Footer](../api/footer.md) code reference
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.Footer
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ The example below shows an app with a `Header`.
|
|||||||
|
|
||||||
This widget sends no messages.
|
This widget sends no messages.
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [Header](../api/header.md) code reference
|
|
||||||
|
::: textual.widgets.Header
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -32,9 +32,8 @@ The example below shows how you might create a simple form using two `Input` wid
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.Input.Changed
|
- [Input.Changed][textual.widgets.Input.Changed]
|
||||||
|
- [Input.Submitted][textual.widgets.Input.Submitted]
|
||||||
### ::: textual.widgets.Input.Submitted
|
|
||||||
|
|
||||||
## Bindings
|
## Bindings
|
||||||
|
|
||||||
@@ -58,6 +57,9 @@ The input widget provides the following component classes:
|
|||||||
|
|
||||||
* The spacing around the text content is due to border. To remove it, set `border: none;` in your CSS.
|
* The spacing around the text content is due to border. To remove it, set `border: none;` in your CSS.
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [Input](../api/input.md) code reference
|
|
||||||
|
::: textual.widgets.Input
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ This widget has no reactive attributes.
|
|||||||
|
|
||||||
This widget sends no messages.
|
This widget sends no messages.
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [Label](../api/label.md) code reference
|
|
||||||
|
::: textual.widgets.Label
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -26,16 +26,19 @@ of multiple `ListItem`s. The arrow keys can be used to navigate the list.
|
|||||||
## Reactive Attributes
|
## Reactive Attributes
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|---------------|--------|---------|--------------------------------------|
|
| ------------- | ------ | ------- | ------------------------------------ |
|
||||||
| `highlighted` | `bool` | `False` | True if this ListItem is highlighted |
|
| `highlighted` | `bool` | `False` | True if this ListItem is highlighted |
|
||||||
|
|
||||||
|
|
||||||
#### Attributes
|
#### Attributes
|
||||||
|
|
||||||
| attribute | type | purpose |
|
| attribute | type | purpose |
|
||||||
|-----------|------------|-----------------------------|
|
| --------- | ---------- | --------------------------- |
|
||||||
| `item` | `ListItem` | The item that was selected. |
|
| `item` | `ListItem` | The item that was selected. |
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [ListItem](../api/list_item.md) code reference
|
|
||||||
|
::: textual.widgets.ListItem
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -37,9 +37,8 @@ The example below shows an app with a simple `ListView`.
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.ListView.Highlighted
|
- [ListView.Highlighted][textual.widgets.ListView.Highlighted]
|
||||||
|
- [ListView.Selected][textual.widgets.ListView.Selected]
|
||||||
### ::: textual.widgets.ListView.Selected
|
|
||||||
|
|
||||||
## Bindings
|
## Bindings
|
||||||
|
|
||||||
@@ -50,6 +49,9 @@ The list view widget defines the following bindings:
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
show_root_toc_entry: false
|
show_root_toc_entry: false
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [ListView](../api/list_view.md) code reference
|
|
||||||
|
::: textual.widgets.ListView
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ LoadingIndicator {
|
|||||||
```python
|
```python
|
||||||
--8<-- "docs/examples/widgets/loading_indicator.py"
|
--8<-- "docs/examples/widgets/loading_indicator.py"
|
||||||
```
|
```
|
||||||
|
---
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
* [LoadingIndicator](../api/loading_indicator.md) code reference
|
::: textual.widgets.LoadingIndicator
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -29,14 +29,20 @@ The following example displays Markdown from a string.
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.Markdown.TableOfContentsUpdated
|
- [Markdown.TableOfContentsUpdated][textual.widgets.Markdown.TableOfContentsUpdated]
|
||||||
|
- [Markdown.TableOfContentsSelected][textual.widgets.Markdown.TableOfContentsSelected]
|
||||||
### ::: textual.widgets.Markdown.TableOfContentsSelected
|
- [Markdown.LinkClicked][textual.widgets.Markdown.LinkClicked]
|
||||||
|
|
||||||
### ::: textual.widgets.Markdown.LinkClicked
|
|
||||||
|
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
* [Markdown][textual.widgets.Markdown] code reference
|
|
||||||
* [MarkdownViewer][textual.widgets.MarkdownViewer] code reference
|
* [MarkdownViewer][textual.widgets.MarkdownViewer] code reference
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.Markdown
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -35,5 +35,13 @@ The following example displays Markdown from a string and a Table of Contents.
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
* [MarkdownViewer][textual.widgets.MarkdownViewer] code reference
|
|
||||||
* [Markdown][textual.widgets.Markdown] code reference
|
* [Markdown][textual.widgets.Markdown] code reference
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.MarkdownViewer
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -82,14 +82,13 @@ tables](https://rich.readthedocs.io/en/latest/tables.html):
|
|||||||
## Reactive Attributes
|
## Reactive Attributes
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|---------------|-----------------|---------|---------------------------------------------------------------------------|
|
| ------------- | --------------- | ------- | ------------------------------------------------------------------------- |
|
||||||
| `highlighted` | `int` \| `None` | `None` | The index of the highlighted option. `None` means nothing is highlighted. |
|
| `highlighted` | `int` \| `None` | `None` | The index of the highlighted option. `None` means nothing is highlighted. |
|
||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.OptionList.OptionHighlighted
|
- [OptionList.OptionHighlight][textual.widgets.OptionList.OptionHighlighted]
|
||||||
|
- [OptionList.OptionSelected][textual.widgets.OptionList.OptionSelected]
|
||||||
### ::: textual.widgets.OptionList.OptionSelected
|
|
||||||
|
|
||||||
Both of the messages above inherit from this common base, which makes
|
Both of the messages above inherit from this common base, which makes
|
||||||
available the following properties relating to the `OptionList` and the
|
available the following properties relating to the `OptionList` and the
|
||||||
@@ -122,6 +121,8 @@ The option list provides the following component classes:
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
show_root_toc_entry: false
|
show_root_toc_entry: false
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
* [OptionList][textual.widgets.OptionList] code reference
|
|
||||||
|
::: textual.widgets.OptionList
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ The example below shows each placeholder variant.
|
|||||||
## Reactive Attributes
|
## Reactive Attributes
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| ---------- | ------ | ----------- | -------------------------------------------------- |
|
| --------- | ----- | ----------- | -------------------------------------------------- |
|
||||||
| `variant` | `str` | `"default"` | Styling variant. One of `default`, `size`, `text`. |
|
| `variant` | `str` | `"default"` | Styling variant. One of `default`, `size`, `text`. |
|
||||||
|
|
||||||
|
|
||||||
@@ -43,6 +43,9 @@ The example below shows each placeholder variant.
|
|||||||
|
|
||||||
This widget sends no messages.
|
This widget sends no messages.
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [Placeholder](../api/placeholder.md) code reference
|
|
||||||
|
::: textual.widgets.Placeholder
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -56,9 +56,15 @@ The radio button widget provides the following component classes:
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.RadioButton.Changed
|
- [RadioButton.Changed][textual.widgets.RadioButton.Changed]
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [RadioButton](../api/radiobutton.md) code reference
|
|
||||||
- [RadioSet](./radioset.md)
|
- [RadioSet](./radioset.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.RadioButton
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ The example below shows two radio sets, one built using a collection of
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.RadioSet.Changed
|
- [RadioSet.Changed][textual.widgets.RadioSet.Changed]
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
@@ -56,5 +56,12 @@ Here is an example of using the message to react to changes in a `RadioSet`:
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [RadioSet](../api/radioset.md) code reference
|
|
||||||
- [RadioButton](./radiobutton.md)
|
- [RadioButton](./radiobutton.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.RadioSet
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -31,5 +31,12 @@ This widget sends no messages.
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
* [Static](../api/static.md) code reference
|
|
||||||
* [Label](./label.md)
|
* [Label](./label.md)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.Static
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -52,12 +52,15 @@ The switch widget provides the following component classes:
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.Switch.Changed
|
- [Switch.Changed][textual.widgets.Switch.Changed]
|
||||||
|
|
||||||
## Additional Notes
|
## Additional Notes
|
||||||
|
|
||||||
- To remove the spacing around a `Switch`, set `border: none;` and `padding: 0;`.
|
- To remove the spacing around a `Switch`, set `border: none;` and `padding: 0;`.
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
- [Switch](../api/switch.md) code reference
|
|
||||||
|
::: textual.widgets.Switch
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -103,6 +103,22 @@ The following example contains a `TabbedContent` with three tabs.
|
|||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [TabbedContent](../api/tabbed_content.md) code reference.
|
|
||||||
- [Tabs](../api/tabs.md) code reference.
|
- [Tabs](tabs.md)
|
||||||
- [ContentSwitcher](../api/content_switcher.md) code reference.
|
- [ContentSwitcher](content_switcher.md)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.TabbedContent
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.TabPane
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ The following example adds a `Tabs` widget above a text label. Press ++a++ to ad
|
|||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
### ::: textual.widgets.Tabs.TabActivated
|
- [Tabs.TabActivate][textual.widgets.Tabs.TabActivated]
|
||||||
### ::: textual.widgets.Tabs.Cleared
|
- [Tabs.Cleared][textual.widgets.Tabs.Cleared]
|
||||||
|
|
||||||
## Bindings
|
## Bindings
|
||||||
|
|
||||||
@@ -73,6 +73,17 @@ The Tabs widget defines the following bindings:
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
show_root_toc_entry: false
|
show_root_toc_entry: false
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
- [Tabs](../api/tabs.md) code reference
|
---
|
||||||
|
|
||||||
|
|
||||||
|
::: textual.widgets.Tabs
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
::: textual.widgets.Tab
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ The example below shows an application showing a `TextLog` with different kinds
|
|||||||
This widget sends no messages.
|
This widget sends no messages.
|
||||||
|
|
||||||
|
|
||||||
## See Also
|
---
|
||||||
|
|
||||||
* [TextLog](../api/text_log.md) code reference
|
|
||||||
|
::: textual.widgets.TextLog
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -62,7 +62,16 @@ The tree widget provides the following component classes:
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
show_root_toc_entry: false
|
show_root_toc_entry: false
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
* [Tree][textual.widgets.Tree] code reference
|
---
|
||||||
* [TreeNode][textual.widgets.tree.TreeNode] code reference
|
|
||||||
|
|
||||||
|
::: textual.widgets.Tree
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
::: textual.widgets.tree.TreeNode
|
||||||
|
options:
|
||||||
|
heading_level: 2
|
||||||
|
|||||||
@@ -152,50 +152,25 @@ nav:
|
|||||||
- "api/app.md"
|
- "api/app.md"
|
||||||
- "api/await_remove.md"
|
- "api/await_remove.md"
|
||||||
- "api/binding.md"
|
- "api/binding.md"
|
||||||
- "api/button.md"
|
|
||||||
- "api/checkbox.md"
|
|
||||||
- "api/color.md"
|
- "api/color.md"
|
||||||
- "api/containers.md"
|
- "api/containers.md"
|
||||||
- "api/content_switcher.md"
|
|
||||||
- "api/coordinate.md"
|
- "api/coordinate.md"
|
||||||
- "api/data_table.md"
|
|
||||||
- "api/directory_tree.md"
|
|
||||||
- "api/dom_node.md"
|
- "api/dom_node.md"
|
||||||
- "api/events.md"
|
- "api/events.md"
|
||||||
- "api/footer.md"
|
|
||||||
- "api/geometry.md"
|
- "api/geometry.md"
|
||||||
- "api/header.md"
|
|
||||||
- "api/index.md"
|
- "api/index.md"
|
||||||
- "api/input.md"
|
- "api/logger.md"
|
||||||
- "api/label.md"
|
|
||||||
- "api/list_item.md"
|
|
||||||
- "api/list_view.md"
|
|
||||||
- "api/loading_indicator.md"
|
|
||||||
- "api/logging.md"
|
- "api/logging.md"
|
||||||
- "api/markdown_viewer.md"
|
|
||||||
- "api/markdown.md"
|
|
||||||
- "api/message_pump.md"
|
- "api/message_pump.md"
|
||||||
- "api/message.md"
|
- "api/message.md"
|
||||||
- "api/option_list.md"
|
|
||||||
- "api/pilot.md"
|
- "api/pilot.md"
|
||||||
- "api/placeholder.md"
|
|
||||||
- "api/query.md"
|
- "api/query.md"
|
||||||
- "api/radiobutton.md"
|
|
||||||
- "api/radioset.md"
|
|
||||||
- "api/reactive.md"
|
- "api/reactive.md"
|
||||||
- "api/screen.md"
|
- "api/screen.md"
|
||||||
- "api/scroll_view.md"
|
- "api/scroll_view.md"
|
||||||
- "api/static.md"
|
|
||||||
- "api/strip.md"
|
- "api/strip.md"
|
||||||
- "api/switch.md"
|
|
||||||
- "api/tabbed_content.md"
|
|
||||||
- "api/tabs.md"
|
|
||||||
- "api/text_log.md"
|
|
||||||
- "api/timer.md"
|
- "api/timer.md"
|
||||||
- "api/toggle_button.md"
|
|
||||||
- "api/tree.md"
|
|
||||||
- "api/walk.md"
|
- "api/walk.md"
|
||||||
- "api/welcome.md"
|
|
||||||
- "api/widget.md"
|
- "api/widget.md"
|
||||||
- "api/work.md"
|
- "api/work.md"
|
||||||
- "api/worker.md"
|
- "api/worker.md"
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
from functools import partial, wraps
|
|
||||||
from typing import TYPE_CHECKING, Callable
|
from typing import TYPE_CHECKING, Callable
|
||||||
|
|
||||||
import rich.repr
|
import rich.repr
|
||||||
|
|||||||
@@ -139,11 +139,11 @@ class BoundAnimator:
|
|||||||
attribute: Name of the attribute to animate.
|
attribute: Name of the attribute to animate.
|
||||||
value: The value to animate to.
|
value: The value to animate to.
|
||||||
final_value: The final value of the animation. Defaults to `value` if not set.
|
final_value: The final value of the animation. Defaults to `value` if not set.
|
||||||
duration: The duration of the animate. Defaults to None.
|
duration: The duration of the animate.
|
||||||
speed: The speed of the animation. Defaults to None.
|
speed: The speed of the animation.
|
||||||
delay: A delay (in seconds) before the animation starts. Defaults to 0.0.
|
delay: A delay (in seconds) before the animation starts.
|
||||||
easing: An easing method. Defaults to "in_out_cubic".
|
easing: An easing method.
|
||||||
on_complete: A callable to invoke when the animation is finished. Defaults to None.
|
on_complete: A callable to invoke when the animation is finished.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
start_value = getattr(self._obj, attribute)
|
start_value = getattr(self._obj, attribute)
|
||||||
@@ -237,11 +237,11 @@ class Animator:
|
|||||||
obj: The object containing the attribute.
|
obj: The object containing the attribute.
|
||||||
attribute: The name of the attribute.
|
attribute: The name of the attribute.
|
||||||
value: The destination value of the attribute.
|
value: The destination value of the attribute.
|
||||||
final_value: The final value, or ellipsis if it is the same as ``value``. Defaults to Ellipsis/
|
final_value: The final value, or ellipsis if it is the same as ``value``.
|
||||||
duration: The duration of the animation, or ``None`` to use speed. Defaults to ``None``.
|
duration: The duration of the animation, or ``None`` to use speed.
|
||||||
speed: The speed of the animation. Defaults to None.
|
speed: The speed of the animation.
|
||||||
easing: An easing function. Defaults to DEFAULT_EASING.
|
easing: An easing function.
|
||||||
delay: Number of seconds to delay the start of the animation by. Defaults to 0.
|
delay: Number of seconds to delay the start of the animation by.
|
||||||
on_complete: Callback to run after the animation completes.
|
on_complete: Callback to run after the animation completes.
|
||||||
"""
|
"""
|
||||||
animate_callback = partial(
|
animate_callback = partial(
|
||||||
@@ -280,10 +280,10 @@ class Animator:
|
|||||||
obj: The object containing the attribute.
|
obj: The object containing the attribute.
|
||||||
attribute: The name of the attribute.
|
attribute: The name of the attribute.
|
||||||
value: The destination value of the attribute.
|
value: The destination value of the attribute.
|
||||||
final_value: The final value, or ellipsis if it is the same as ``value``. Defaults to ....
|
final_value: The final value, or ellipsis if it is the same as ``value``.
|
||||||
duration: The duration of the animation, or ``None`` to use speed. Defaults to ``None``.
|
duration: The duration of the animation, or ``None`` to use speed.
|
||||||
speed: The speed of the animation. Defaults to None.
|
speed: The speed of the animation.
|
||||||
easing: An easing function. Defaults to DEFAULT_EASING.
|
easing: An easing function.
|
||||||
on_complete: Callback to run after the animation completes.
|
on_complete: Callback to run after the animation completes.
|
||||||
"""
|
"""
|
||||||
if not hasattr(obj, attribute):
|
if not hasattr(obj, attribute):
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ class LRUCache(Generic[CacheKey, CacheValue]):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key
|
key: Key
|
||||||
default: Default to return if key is not present. Defaults to None.
|
default: Default to return if key is not present.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Either the value or a default.
|
Either the value or a default.
|
||||||
@@ -256,7 +256,7 @@ class FIFOCache(Generic[CacheKey, CacheValue]):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key
|
key: Key
|
||||||
default: Default to return if key is not present. Defaults to None.
|
default: Default to return if key is not present.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Either the value or a default.
|
Either the value or a default.
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
A decorator used to create [workers](/guide/workers).
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from functools import partial, wraps
|
from functools import partial, wraps
|
||||||
@@ -53,7 +60,7 @@ def work(
|
|||||||
exit_on_error: bool = True,
|
exit_on_error: bool = True,
|
||||||
exclusive: bool = False,
|
exclusive: bool = False,
|
||||||
) -> Callable[FactoryParamSpec, Worker[ReturnType]] | Decorator:
|
) -> Callable[FactoryParamSpec, Worker[ReturnType]] | Decorator:
|
||||||
"""Worker decorator factory.
|
"""A decorator used to create [workers](/guide/workers).
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
method: A function or coroutine.
|
method: A function or coroutine.
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
"""
|
||||||
|
A class to manage [workers](/guide/workers) for an app.
|
||||||
|
|
||||||
|
You access this object via [App.workers][textual.app.App.workers] or [Widget.workers][textual.dom.DOMNode.workers].
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ from ._wait import wait_for_idle
|
|||||||
from ._worker_manager import WorkerManager
|
from ._worker_manager import WorkerManager
|
||||||
from .actions import ActionParseResult, SkipAction
|
from .actions import ActionParseResult, SkipAction
|
||||||
from .await_remove import AwaitRemove
|
from .await_remove import AwaitRemove
|
||||||
from .binding import Binding, Bindings
|
from .binding import Binding, _Bindings
|
||||||
from .css.query import NoMatches
|
from .css.query import NoMatches
|
||||||
from .css.stylesheet import Stylesheet
|
from .css.stylesheet import Stylesheet
|
||||||
from .design import ColorSystem
|
from .design import ColorSystem
|
||||||
@@ -242,10 +242,10 @@ CallThreadReturnType = TypeVar("CallThreadReturnType")
|
|||||||
class App(Generic[ReturnType], DOMNode):
|
class App(Generic[ReturnType], DOMNode):
|
||||||
"""The base class for Textual Applications.
|
"""The base class for Textual Applications.
|
||||||
Args:
|
Args:
|
||||||
driver_class: Driver class or ``None`` to auto-detect. Defaults to None.
|
driver_class: Driver class or ``None`` to auto-detect.
|
||||||
css_path: Path to CSS or ``None`` for no CSS file.
|
css_path: Path to CSS or ``None`` for no CSS file.
|
||||||
Defaults to None. To load multiple CSS files, pass a list of strings or paths which will be loaded in order.
|
To load multiple CSS files, pass a list of strings or paths which will be loaded in order.
|
||||||
watch_css: Watch CSS for changes. Defaults to False.
|
watch_css: Watch CSS for changes.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
CssPathError: When the supplied CSS path(s) are an unexpected type.
|
CssPathError: When the supplied CSS path(s) are an unexpected type.
|
||||||
@@ -436,7 +436,12 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def workers(self) -> WorkerManager:
|
def workers(self) -> WorkerManager:
|
||||||
"""A worker manager."""
|
"""The worker manager.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An object to manage workers.
|
||||||
|
|
||||||
|
"""
|
||||||
return self._workers
|
return self._workers
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -446,7 +451,12 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def children(self) -> Sequence["Widget"]:
|
def children(self) -> Sequence["Widget"]:
|
||||||
"""A view on to the children which contains just the screen."""
|
"""A view on to the App's children (just the screen).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A sequence of widgets.
|
||||||
|
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
return (self.screen,)
|
return (self.screen,)
|
||||||
except ScreenError:
|
except ScreenError:
|
||||||
@@ -489,12 +499,12 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
Args:
|
Args:
|
||||||
attribute: Name of the attribute to animate.
|
attribute: Name of the attribute to animate.
|
||||||
value: The value to animate to.
|
value: The value to animate to.
|
||||||
final_value: The final value of the animation. Defaults to `value` if not set.
|
final_value: The final value of the animation.
|
||||||
duration: The duration of the animate. Defaults to None.
|
duration: The duration of the animate.
|
||||||
speed: The speed of the animation. Defaults to None.
|
speed: The speed of the animation.
|
||||||
delay: A delay (in seconds) before the animation starts. Defaults to 0.0.
|
delay: A delay (in seconds) before the animation starts.
|
||||||
easing: An easing method. Defaults to "in_out_cubic".
|
easing: An easing method.
|
||||||
on_complete: A callable to invoke when the animation is finished. Defaults to None.
|
on_complete: A callable to invoke when the animation is finished.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self._animate(
|
self._animate(
|
||||||
@@ -520,7 +530,12 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def screen_stack(self) -> list[Screen]:
|
def screen_stack(self) -> list[Screen]:
|
||||||
"""A *copy* of the screen stack."""
|
"""A *copy* of the screen stack.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A snapshot of the current state of the screen stack.
|
||||||
|
|
||||||
|
"""
|
||||||
return self._screen_stack.copy()
|
return self._screen_stack.copy()
|
||||||
|
|
||||||
def exit(
|
def exit(
|
||||||
@@ -529,7 +544,7 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
"""Exit the app, and return the supplied result.
|
"""Exit the app, and return the supplied result.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
result: Return value. Defaults to None.
|
result: Return value.
|
||||||
message: Optional message to display on exit.
|
message: Optional message to display on exit.
|
||||||
"""
|
"""
|
||||||
self._exit = True
|
self._exit = True
|
||||||
@@ -540,7 +555,12 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def focused(self) -> Widget | None:
|
def focused(self) -> Widget | None:
|
||||||
"""The widget that is focused on the currently active screen."""
|
"""The widget that is focused on the currently active screen.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The currently focused widget, or `None` if nothing is focused.
|
||||||
|
|
||||||
|
"""
|
||||||
return self.screen.focused
|
return self.screen.focused
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -666,7 +686,12 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self) -> Size:
|
def size(self) -> Size:
|
||||||
"""The size of the terminal."""
|
"""The size of the terminal.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Size of the terminal.
|
||||||
|
|
||||||
|
"""
|
||||||
if self._driver is not None and self._driver._size is not None:
|
if self._driver is not None and self._driver._size is not None:
|
||||||
width, height = self._driver._size
|
width, height = self._driver._size
|
||||||
else:
|
else:
|
||||||
@@ -675,7 +700,12 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def log(self) -> Logger:
|
def log(self) -> Logger:
|
||||||
"""The logger object."""
|
"""Textual log interface.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A Textual logger.
|
||||||
|
|
||||||
|
"""
|
||||||
return self._logger
|
return self._logger
|
||||||
|
|
||||||
def _log(
|
def _log(
|
||||||
@@ -699,7 +729,7 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
```
|
```
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
verbosity: Verbosity level 0-3. Defaults to 1.
|
verbosity: Verbosity level 0-3.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
devtools = self.devtools
|
devtools = self.devtools
|
||||||
@@ -786,7 +816,7 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
"""Save an SVG "screenshot". This action will save an SVG file containing the current contents of the screen.
|
"""Save an SVG "screenshot". This action will save an SVG file containing the current contents of the screen.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filename: Filename of screenshot, or None to auto-generate. Defaults to None.
|
filename: Filename of screenshot, or None to auto-generate.
|
||||||
path: Path to directory. Defaults to current working directory.
|
path: Path to directory. Defaults to current working directory.
|
||||||
"""
|
"""
|
||||||
self.save_screenshot(filename, path)
|
self.save_screenshot(filename, path)
|
||||||
@@ -796,7 +826,7 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
title: The title of the exported screenshot or None
|
title: The title of the exported screenshot or None
|
||||||
to use app title. Defaults to None.
|
to use app title.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
assert self._driver is not None, "App must be running"
|
assert self._driver is not None, "App must be running"
|
||||||
@@ -826,7 +856,7 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
filename: Filename of SVG screenshot, or None to auto-generate
|
filename: Filename of SVG screenshot, or None to auto-generate
|
||||||
a filename with the date and time. Defaults to None.
|
a filename with the date and time.
|
||||||
path: Path to directory for output. Defaults to current working directory.
|
path: Path to directory for output. Defaults to current working directory.
|
||||||
time_format: Date and time format to use if filename is None.
|
time_format: Date and time format to use if filename is None.
|
||||||
Defaults to a format like ISO 8601 with some reserved characters replaced with underscores.
|
Defaults to a format like ISO 8601 with some reserved characters replaced with underscores.
|
||||||
@@ -865,9 +895,9 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
Args:
|
Args:
|
||||||
keys: A comma separated list of keys, i.e.
|
keys: A comma separated list of keys, i.e.
|
||||||
action: Action to bind to.
|
action: Action to bind to.
|
||||||
description: Short description of action. Defaults to "".
|
description: Short description of action.
|
||||||
show: Show key in UI. Defaults to True.
|
show: Show key in UI.
|
||||||
key_display: Replacement text for key, or None to use default. Defaults to None.
|
key_display: Replacement text for key, or None to use default.
|
||||||
"""
|
"""
|
||||||
self._bindings.bind(
|
self._bindings.bind(
|
||||||
keys, action, description, show=show, key_display=key_display
|
keys, action, description, show=show, key_display=key_display
|
||||||
@@ -930,9 +960,9 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
"""An asynchronous context manager for testing app.
|
"""An asynchronous context manager for testing app.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
headless: Run in headless mode (no output or input). Defaults to True.
|
headless: Run in headless mode (no output or input).
|
||||||
size: Force terminal size to `(WIDTH, HEIGHT)`,
|
size: Force terminal size to `(WIDTH, HEIGHT)`,
|
||||||
or None to auto-detect. Defaults to None.
|
or None to auto-detect.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from .pilot import Pilot
|
from .pilot import Pilot
|
||||||
@@ -981,9 +1011,9 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
"""Run the app asynchronously.
|
"""Run the app asynchronously.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
headless: Run in headless mode (no output). Defaults to False.
|
headless: Run in headless mode (no output).
|
||||||
size: Force terminal size to `(WIDTH, HEIGHT)`,
|
size: Force terminal size to `(WIDTH, HEIGHT)`,
|
||||||
or None to auto-detect. Defaults to None.
|
or None to auto-detect.
|
||||||
auto_pilot: An auto pilot coroutine.
|
auto_pilot: An auto pilot coroutine.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -1042,9 +1072,9 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
"""Run the app.
|
"""Run the app.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
headless: Run in headless mode (no output). Defaults to False.
|
headless: Run in headless mode (no output).
|
||||||
size: Force terminal size to `(WIDTH, HEIGHT)`,
|
size: Force terminal size to `(WIDTH, HEIGHT)`,
|
||||||
or None to auto-detect. Defaults to None.
|
or None to auto-detect.
|
||||||
auto_pilot: An auto pilot coroutine.
|
auto_pilot: An auto pilot coroutine.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -1119,7 +1149,6 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
Args:
|
Args:
|
||||||
id: The ID of the node to search for.
|
id: The ID of the node to search for.
|
||||||
expect_type: Require the object be of the supplied type, or None for any type.
|
expect_type: Require the object be of the supplied type, or None for any type.
|
||||||
Defaults to None.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The first child of this node with the specified ID.
|
The first child of this node with the specified ID.
|
||||||
@@ -1918,7 +1947,7 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
"""Refresh CSS.
|
"""Refresh CSS.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
animate: Also execute CSS animations. Defaults to True.
|
animate: Also execute CSS animations.
|
||||||
"""
|
"""
|
||||||
stylesheet = self.app.stylesheet
|
stylesheet = self.app.stylesheet
|
||||||
stylesheet.set_variables(self.get_css_variables())
|
stylesheet.set_variables(self.get_css_variables())
|
||||||
@@ -1973,14 +2002,14 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
self.console.bell()
|
self.console.bell()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _binding_chain(self) -> list[tuple[DOMNode, Bindings]]:
|
def _binding_chain(self) -> list[tuple[DOMNode, _Bindings]]:
|
||||||
"""Get a chain of nodes and bindings to consider.
|
"""Get a chain of nodes and bindings to consider.
|
||||||
|
|
||||||
If no widget is focused, returns the bindings from both the screen and the app level bindings.
|
If no widget is focused, returns the bindings from both the screen and the app level bindings.
|
||||||
Otherwise, combines all the bindings from the currently focused node up the DOM to the root App.
|
Otherwise, combines all the bindings from the currently focused node up the DOM to the root App.
|
||||||
"""
|
"""
|
||||||
focused = self.focused
|
focused = self.focused
|
||||||
namespace_bindings: list[tuple[DOMNode, Bindings]]
|
namespace_bindings: list[tuple[DOMNode, _Bindings]]
|
||||||
|
|
||||||
if focused is None:
|
if focused is None:
|
||||||
namespace_bindings = [
|
namespace_bindings = [
|
||||||
@@ -1995,7 +2024,7 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
return namespace_bindings
|
return namespace_bindings
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _modal_binding_chain(self) -> list[tuple[DOMNode, Bindings]]:
|
def _modal_binding_chain(self) -> list[tuple[DOMNode, _Bindings]]:
|
||||||
"""The binding chain, ignoring everything before the last modal."""
|
"""The binding chain, ignoring everything before the last modal."""
|
||||||
binding_chain = self._binding_chain
|
binding_chain = self._binding_chain
|
||||||
for index, (node, _bindings) in enumerate(binding_chain, 1):
|
for index, (node, _bindings) in enumerate(binding_chain, 1):
|
||||||
@@ -2061,7 +2090,7 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
Args:
|
Args:
|
||||||
action: Action encoded in a string.
|
action: Action encoded in a string.
|
||||||
default_namespace: Namespace to use if not provided in the action,
|
default_namespace: Namespace to use if not provided in the action,
|
||||||
or None to use app. Defaults to None.
|
or None to use app.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if the event has handled.
|
True if the event has handled.
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
"""Provides the type of an awaitable remove."""
|
"""
|
||||||
|
|
||||||
|
An *optionally* awaitable object returned by methods that remove widgets.
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from asyncio import Event, Task
|
from asyncio import Event, Task
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
A binding maps a key press on to an action.
|
||||||
|
|
||||||
|
See [bindings](/guide/input#bindings) in the guide for details.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
@@ -44,7 +53,7 @@ class Binding:
|
|||||||
|
|
||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class Bindings:
|
class _Bindings:
|
||||||
"""Manage a set of bindings."""
|
"""Manage a set of bindings."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -98,13 +107,13 @@ class Bindings:
|
|||||||
else {}
|
else {}
|
||||||
)
|
)
|
||||||
|
|
||||||
def copy(self) -> Bindings:
|
def copy(self) -> _Bindings:
|
||||||
"""Return a copy of this instance.
|
"""Return a copy of this instance.
|
||||||
|
|
||||||
Return:
|
Return:
|
||||||
New bindings object.
|
New bindings object.
|
||||||
"""
|
"""
|
||||||
copy = Bindings()
|
copy = _Bindings()
|
||||||
copy.keys = self.keys.copy()
|
copy.keys = self.keys.copy()
|
||||||
return copy
|
return copy
|
||||||
|
|
||||||
@@ -112,7 +121,7 @@ class Bindings:
|
|||||||
yield self.keys
|
yield self.keys
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def merge(cls, bindings: Iterable[Bindings]) -> Bindings:
|
def merge(cls, bindings: Iterable[_Bindings]) -> _Bindings:
|
||||||
"""Merge a bindings. Subsequent bound keys override initial keys.
|
"""Merge a bindings. Subsequent bound keys override initial keys.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -124,7 +133,7 @@ class Bindings:
|
|||||||
keys: dict[str, Binding] = {}
|
keys: dict[str, Binding] = {}
|
||||||
for _bindings in bindings:
|
for _bindings in bindings:
|
||||||
keys.update(_bindings.keys)
|
keys.update(_bindings.keys)
|
||||||
return Bindings(keys.values())
|
return _Bindings(keys.values())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def shown_keys(self) -> list[Binding]:
|
def shown_keys(self) -> list[Binding]:
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
This module contains a powerful Color class which Textual uses to expose colors.
|
This module contains a powerful Color class which Textual uses to expose colors.
|
||||||
|
|
||||||
The only exception would be for Rich renderables, which require a rich.color.Color instance.
|
|
||||||
You can convert from a Textual color to a Rich color with the [rich_color][textual.color.Color.rich_color] property.
|
|
||||||
|
|
||||||
## Named colors
|
## Named colors
|
||||||
|
|
||||||
The following named colors are used by the [parse][textual.color.Color.parse] method.
|
The following named colors are used by the [parse][textual.color.Color.parse] method.
|
||||||
@@ -46,6 +43,7 @@ from rich.color import ColorType
|
|||||||
from rich.color_triplet import ColorTriplet
|
from rich.color_triplet import ColorTriplet
|
||||||
from rich.style import Style
|
from rich.style import Style
|
||||||
from rich.text import Text
|
from rich.text import Text
|
||||||
|
from typing_extensions import Final
|
||||||
|
|
||||||
from textual.css.scalar import percentage_string_to_float
|
from textual.css.scalar import percentage_string_to_float
|
||||||
from textual.css.tokenize import CLOSE_BRACE, COMMA, DECIMAL, OPEN_BRACE, PERCENT
|
from textual.css.tokenize import CLOSE_BRACE, COMMA, DECIMAL, OPEN_BRACE, PERCENT
|
||||||
@@ -58,14 +56,14 @@ _TRUECOLOR = ColorType.TRUECOLOR
|
|||||||
|
|
||||||
|
|
||||||
class HSL(NamedTuple):
|
class HSL(NamedTuple):
|
||||||
"""A color in HLS format."""
|
"""A color in HLS (Hue, Saturation, Lightness) format."""
|
||||||
|
|
||||||
h: float
|
h: float
|
||||||
"""Hue"""
|
"""Hue in range 0 to 1."""
|
||||||
s: float
|
s: float
|
||||||
"""Saturation"""
|
"""Saturation in range 0 to 1."""
|
||||||
l: float
|
l: float
|
||||||
"""Lightness"""
|
"""Lightness in range 0 to 1."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def css(self) -> str:
|
def css(self) -> str:
|
||||||
@@ -73,28 +71,32 @@ class HSL(NamedTuple):
|
|||||||
h, s, l = self
|
h, s, l = self
|
||||||
|
|
||||||
def as_str(number: float) -> str:
|
def as_str(number: float) -> str:
|
||||||
|
"""Format a float."""
|
||||||
return f"{number:.1f}".rstrip("0").rstrip(".")
|
return f"{number:.1f}".rstrip("0").rstrip(".")
|
||||||
|
|
||||||
return f"hsl({as_str(h*360)},{as_str(s*100)}%,{as_str(l*100)}%)"
|
return f"hsl({as_str(h*360)},{as_str(s*100)}%,{as_str(l*100)}%)"
|
||||||
|
|
||||||
|
|
||||||
class HSV(NamedTuple):
|
class HSV(NamedTuple):
|
||||||
"""A color in HSV format."""
|
"""A color in HSV (Hue, Saturation, Value) format."""
|
||||||
|
|
||||||
h: float
|
h: float
|
||||||
"""Hue"""
|
"""Hue in range 0 to 1."""
|
||||||
s: float
|
s: float
|
||||||
"""Saturation"""
|
"""Saturation in range 0 to 1"""
|
||||||
v: float
|
v: float
|
||||||
"""Value"""
|
"""Value un range 0 to 1."""
|
||||||
|
|
||||||
|
|
||||||
class Lab(NamedTuple):
|
class Lab(NamedTuple):
|
||||||
"""A color in CIE-L*ab format."""
|
"""A color in CIE-L*ab format."""
|
||||||
|
|
||||||
L: float
|
L: float
|
||||||
|
"""Lightness in range 0 to 100."""
|
||||||
a: float
|
a: float
|
||||||
|
"""A axis in range -127 to 128."""
|
||||||
b: float
|
b: float
|
||||||
|
"""B axis in range -127 to 128."""
|
||||||
|
|
||||||
|
|
||||||
RE_COLOR = re.compile(
|
RE_COLOR = re.compile(
|
||||||
@@ -126,7 +128,7 @@ class ColorParseError(Exception):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
message: The error message
|
message: The error message
|
||||||
suggested_color: A close color we can suggest. Defaults to None.
|
suggested_color: A close color we can suggest.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, message: str, suggested_color: str | None = None):
|
def __init__(self, message: str, suggested_color: str | None = None):
|
||||||
@@ -136,26 +138,32 @@ class ColorParseError(Exception):
|
|||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class Color(NamedTuple):
|
class Color(NamedTuple):
|
||||||
"""A class to represent a RGB color with an alpha component."""
|
"""A class to represent a color.
|
||||||
|
|
||||||
|
Colors are stored as three values representing the degree of red, green, and blue in a color, and a
|
||||||
|
fourth "alpha" value which defines where the color lies on a gradient of opaque to transparent.
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
r: int
|
r: int
|
||||||
"""Red component (0-255)"""
|
"""Red component in range 0 to 255."""
|
||||||
g: int
|
g: int
|
||||||
"""Green component (0-255)"""
|
"""Green component in range 0 to 255."""
|
||||||
b: int
|
b: int
|
||||||
"""Blue component (0-255)"""
|
"""Blue component in range 0 to 255."""
|
||||||
a: float = 1.0
|
a: float = 1.0
|
||||||
"""Alpha component (0-1)"""
|
"""Alpha component in range 0 to 1."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_rich_color(cls, rich_color: RichColor) -> Color:
|
def from_rich_color(cls, rich_color: RichColor) -> Color:
|
||||||
"""Create a new color from Rich's Color class.
|
"""Create a new color from Rich's Color class.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
rich_color: An instance of rich.color.Color.
|
rich_color: An instance of [Rich color][rich.color.Color].
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A new Color.
|
A new Color instance.
|
||||||
"""
|
"""
|
||||||
r, g, b = rich_color.get_truecolor()
|
r, g, b = rich_color.get_truecolor()
|
||||||
return cls(r, g, b)
|
return cls(r, g, b)
|
||||||
@@ -192,22 +200,12 @@ class Color(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_transparent(self) -> bool:
|
def is_transparent(self) -> bool:
|
||||||
"""Check if the color is transparent, i.e. has 0 alpha.
|
"""Is the color transparent (i.e. has 0 alpha)?"""
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if transparent, otherwise False.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self.a == 0
|
return self.a == 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def clamped(self) -> Color:
|
def clamped(self) -> Color:
|
||||||
"""Get a color with all components saturated to maximum and minimum values.
|
"""A clamped color (this color with all values in expected range)."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
A color object.
|
|
||||||
|
|
||||||
"""
|
|
||||||
r, g, b, a = self
|
r, g, b, a = self
|
||||||
_clamp = clamp
|
_clamp = clamp
|
||||||
color = Color(
|
color = Color(
|
||||||
@@ -243,20 +241,16 @@ class Color(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def rgb(self) -> tuple[int, int, int]:
|
def rgb(self) -> tuple[int, int, int]:
|
||||||
"""Get just the red, green, and blue components.
|
"""A tuple of the red, gree, and blue color components."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
Color components
|
|
||||||
"""
|
|
||||||
r, g, b, _ = self
|
r, g, b, _ = self
|
||||||
return (r, g, b)
|
return (r, g, b)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hsl(self) -> HSL:
|
def hsl(self) -> HSL:
|
||||||
"""Get the color as HSL.
|
"""This color in HSL format.
|
||||||
|
|
||||||
|
HSL color is an alternative way of representing a color, which can be used in certain color calculations.
|
||||||
|
|
||||||
Returns:
|
|
||||||
Color in HSL format.
|
|
||||||
"""
|
"""
|
||||||
r, g, b = self.normalized
|
r, g, b = self.normalized
|
||||||
h, l, s = rgb_to_hls(r, g, b)
|
h, l, s = rgb_to_hls(r, g, b)
|
||||||
@@ -264,10 +258,10 @@ class Color(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def brightness(self) -> float:
|
def brightness(self) -> float:
|
||||||
"""Get the human perceptual brightness.
|
"""The human perceptual brightness.
|
||||||
|
|
||||||
Returns:
|
A value of 1 is returned for pure white, and 0 for pure black.
|
||||||
Brightness value (0-1).
|
Other colors lie on a gradient between the two extremes.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
r, g, b = self.normalized
|
r, g, b = self.normalized
|
||||||
@@ -278,8 +272,7 @@ class Color(NamedTuple):
|
|||||||
def hex(self) -> str:
|
def hex(self) -> str:
|
||||||
"""The color in CSS hex form, with 6 digits for RGB, and 8 digits for RGBA.
|
"""The color in CSS hex form, with 6 digits for RGB, and 8 digits for RGBA.
|
||||||
|
|
||||||
Returns:
|
For example, `"#46b3de"` for an RGB color, or `"#3342457f"` for a color with alpha.
|
||||||
A CSS hex-style color, e.g. `"#46b3de"` or `"#3342457f"`
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
r, g, b, a = self.clamped
|
r, g, b, a = self.clamped
|
||||||
@@ -293,8 +286,7 @@ class Color(NamedTuple):
|
|||||||
def hex6(self) -> str:
|
def hex6(self) -> str:
|
||||||
"""The color in CSS hex form, with 6 digits for RGB. Alpha is ignored.
|
"""The color in CSS hex form, with 6 digits for RGB. Alpha is ignored.
|
||||||
|
|
||||||
Returns:
|
For example, `"#46b3de"`.
|
||||||
A CSS hex-style color, e.g. "#46b3de"
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
r, g, b, _a = self.clamped
|
r, g, b, _a = self.clamped
|
||||||
@@ -302,10 +294,9 @@ class Color(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def css(self) -> str:
|
def css(self) -> str:
|
||||||
"""The color in CSS rgb or rgba form.
|
"""The color in CSS RGB or RGBA form.
|
||||||
|
|
||||||
Returns:
|
For example, `"rgb(10,20,30)"` for an RGB color, or `"rgb(50,70,80,0.5)"` for an RGBA color.
|
||||||
A CSS style color, e.g. `"rgb(10,20,30)"` or `"rgb(50,70,80,0.5)"`
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
r, g, b, a = self
|
r, g, b, a = self
|
||||||
@@ -313,11 +304,7 @@ class Color(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def monochrome(self) -> Color:
|
def monochrome(self) -> Color:
|
||||||
"""Get a monochrome version of this color.
|
"""A monochrome version of this color."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
A new monochrome color.
|
|
||||||
"""
|
|
||||||
r, g, b, a = self
|
r, g, b, a = self
|
||||||
gray = round(r * 0.2126 + g * 0.7152 + b * 0.0722)
|
gray = round(r * 0.2126 + g * 0.7152 + b * 0.0722)
|
||||||
return Color(gray, gray, gray, a)
|
return Color(gray, gray, gray, a)
|
||||||
@@ -358,10 +345,14 @@ class Color(NamedTuple):
|
|||||||
) -> Color:
|
) -> Color:
|
||||||
"""Generate a new color between two colors.
|
"""Generate a new color between two colors.
|
||||||
|
|
||||||
|
This method calculates a new color on a gradient.
|
||||||
|
The position on the gradient is given by `factor`, which is a float between 0 and 1, where 0 is the original color, and 1 is the `destination` color.
|
||||||
|
A value of `gradient` between the two extremes produces a color somewhere between the two end points.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
destination: Another color.
|
destination: Another color.
|
||||||
factor: A blend factor, 0 -> 1.
|
factor: A blend factor, 0 -> 1.
|
||||||
alpha: New alpha for result. Defaults to None.
|
alpha: New alpha for result.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A new color.
|
A new color.
|
||||||
@@ -515,7 +506,7 @@ class Color(NamedTuple):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
amount: Value between 0-1 to reduce luminance by.
|
amount: Value between 0-1 to reduce luminance by.
|
||||||
alpha: Alpha component for new color or None to copy alpha. Defaults to None.
|
alpha: Alpha component for new color or None to copy alpha.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
New color.
|
New color.
|
||||||
@@ -529,7 +520,7 @@ class Color(NamedTuple):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
amount: Value between 0-1 to increase luminance by.
|
amount: Value between 0-1 to increase luminance by.
|
||||||
alpha: Alpha component for new color or None to copy alpha. Defaults to None.
|
alpha: Alpha component for new color or None to copy alpha.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
New color.
|
New color.
|
||||||
@@ -541,8 +532,7 @@ class Color(NamedTuple):
|
|||||||
"""Get a light or dark color that best contrasts this color, for use with text.
|
"""Get a light or dark color that best contrasts this color, for use with text.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
alpha: An alpha value to adjust the pure white / black by.
|
alpha: An alpha value to apply to the result.
|
||||||
Defaults to 0.95.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A new color, either an off-white or off-black
|
A new color, either an off-white or off-black
|
||||||
@@ -597,8 +587,10 @@ class Gradient:
|
|||||||
|
|
||||||
|
|
||||||
# Color constants
|
# Color constants
|
||||||
WHITE = Color(255, 255, 255)
|
WHITE: Final = Color(255, 255, 255)
|
||||||
BLACK = Color(0, 0, 0)
|
"""A constant for pure white."""
|
||||||
|
BLACK: Final = Color(0, 0, 0)
|
||||||
|
"""A constant for pure black."""
|
||||||
|
|
||||||
|
|
||||||
def rgb_to_lab(rgb: Color) -> Lab:
|
def rgb_to_lab(rgb: Color) -> Lab:
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
Container widgets for quick styling.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
from .widget import Widget
|
from .widget import Widget
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
"""
|
||||||
|
A class to store a coordinate, used by the [DataTable][textual.widgets.DataTable].
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import NamedTuple
|
from typing import NamedTuple
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ def friendly_list(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
words: A list of words.
|
words: A list of words.
|
||||||
joiner: The last joiner word. Defaults to "or".
|
joiner: The last joiner word.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List as prose.
|
List as prose.
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class HelpText:
|
|||||||
Attributes:
|
Attributes:
|
||||||
summary: A succinct summary of the issue.
|
summary: A succinct summary of the issue.
|
||||||
bullets: Bullet points which provide additional
|
bullets: Bullet points which provide additional
|
||||||
context around the issue. These are rendered below the summary. Defaults to None.
|
context around the issue. These are rendered below the summary.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ def _join_tokens(tokens: Iterable[Token], joiner: str = "") -> str:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
tokens: Tokens to join
|
tokens: Tokens to join
|
||||||
joiner: String to join on, defaults to ""
|
joiner: String to join on.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The tokens, joined together to form a string.
|
The tokens, joined together to form a string.
|
||||||
|
|||||||
@@ -72,6 +72,21 @@ class DOMQuery(Generic[QueryType]):
|
|||||||
exclude: str | None = None,
|
exclude: str | None = None,
|
||||||
parent: DOMQuery | None = None,
|
parent: DOMQuery | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""Initialize a query object.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
You won't need to construct this manually, as `DOMQuery` objects are returned by [query][textual.dom.DOMNode.query].
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node: A DOM node.
|
||||||
|
filter: Query to filter children in the node.
|
||||||
|
exclude: Query to exclude children in the node.
|
||||||
|
parent: The parent query, if this is the result of filtering another query.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
InvalidQueryFormat: If the format of the query is invalid.
|
||||||
|
"""
|
||||||
self._node = node
|
self._node = node
|
||||||
self._nodes: list[QueryType] | None = None
|
self._nodes: list[QueryType] | None = None
|
||||||
self._filters: list[tuple[SelectorSet, ...]] = (
|
self._filters: list[tuple[SelectorSet, ...]] = (
|
||||||
@@ -95,6 +110,7 @@ class DOMQuery(Generic[QueryType]):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def node(self) -> DOMNode:
|
def node(self) -> DOMNode:
|
||||||
|
"""The node being queried."""
|
||||||
return self._node
|
return self._node
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -193,7 +209,7 @@ class DOMQuery(Generic[QueryType]):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
expect_type: Require matched node is of this type,
|
expect_type: Require matched node is of this type,
|
||||||
or None for any type. Defaults to None.
|
or None for any type.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
WrongType: If the wrong type was found.
|
WrongType: If the wrong type was found.
|
||||||
@@ -228,7 +244,7 @@ class DOMQuery(Generic[QueryType]):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
expect_type: Require matched node is of this type,
|
expect_type: Require matched node is of this type,
|
||||||
or None for any type. Defaults to None.
|
or None for any type.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
WrongType: If the wrong type was found.
|
WrongType: If the wrong type was found.
|
||||||
@@ -272,7 +288,7 @@ class DOMQuery(Generic[QueryType]):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
expect_type: Require matched node is of this type,
|
expect_type: Require matched node is of this type,
|
||||||
or None for any type. Defaults to None.
|
or None for any type.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
WrongType: If the wrong type was found.
|
WrongType: If the wrong type was found.
|
||||||
@@ -305,7 +321,7 @@ class DOMQuery(Generic[QueryType]):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
filter_type: A Widget class to filter results,
|
filter_type: A Widget class to filter results,
|
||||||
or None for no filter. Defaults to None.
|
or None for no filter.
|
||||||
|
|
||||||
Yields:
|
Yields:
|
||||||
Iterator[Widget | ExpectType]: An iterator of Widget instances.
|
Iterator[Widget | ExpectType]: An iterator of Widget instances.
|
||||||
@@ -383,7 +399,7 @@ class DOMQuery(Generic[QueryType]):
|
|||||||
"""Set styles on matched nodes.
|
"""Set styles on matched nodes.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
css: CSS declarations to parser, or None. Defaults to None.
|
css: CSS declarations to parser, or None.
|
||||||
"""
|
"""
|
||||||
_rich_traceback_omit = True
|
_rich_traceback_omit = True
|
||||||
|
|
||||||
@@ -405,8 +421,8 @@ class DOMQuery(Generic[QueryType]):
|
|||||||
"""Refresh matched nodes.
|
"""Refresh matched nodes.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
repaint: Repaint node(s). defaults to True.
|
repaint: Repaint node(s).
|
||||||
layout: Layout node(s). Defaults to False.
|
layout: Layout node(s).
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Query for chaining.
|
Query for chaining.
|
||||||
|
|||||||
@@ -447,7 +447,7 @@ class StylesBase(ABC):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
rule: Name of rule.
|
rule: Name of rule.
|
||||||
default: Default if rule does not exists. Defaults to None.
|
default: Default if rule does not exists.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Rule value or default.
|
Rule value or default.
|
||||||
@@ -511,7 +511,7 @@ class StylesBase(ABC):
|
|||||||
Args:
|
Args:
|
||||||
css: Textual CSS.
|
css: Textual CSS.
|
||||||
path: Path or string indicating source of CSS.
|
path: Path or string indicating source of CSS.
|
||||||
node: Node to associate with the Styles. Defaults to None.
|
node: Node to associate with the Styles.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A Styles instance containing result of parsing CSS.
|
A Styles instance containing result of parsing CSS.
|
||||||
@@ -1078,11 +1078,11 @@ class RenderStyles(StylesBase):
|
|||||||
attribute: Name of the attribute to animate.
|
attribute: Name of the attribute to animate.
|
||||||
value: The value to animate to.
|
value: The value to animate to.
|
||||||
final_value: The final value of the animation. Defaults to `value` if not set.
|
final_value: The final value of the animation. Defaults to `value` if not set.
|
||||||
duration: The duration of the animate. Defaults to None.
|
duration: The duration of the animate.
|
||||||
speed: The speed of the animation. Defaults to None.
|
speed: The speed of the animation.
|
||||||
delay: A delay (in seconds) before the animation starts. Defaults to 0.0.
|
delay: A delay (in seconds) before the animation starts.
|
||||||
easing: An easing method. Defaults to "in_out_cubic".
|
easing: An easing method.
|
||||||
on_complete: A callable to invoke when the animation is finished. Defaults to None.
|
on_complete: A callable to invoke when the animation is finished.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self._animate is None:
|
if self._animate is None:
|
||||||
|
|||||||
@@ -275,7 +275,6 @@ class Stylesheet:
|
|||||||
Args:
|
Args:
|
||||||
css: String with CSS source.
|
css: String with CSS source.
|
||||||
path: The path of the source if a file, or some other identifier.
|
path: The path of the source if a file, or some other identifier.
|
||||||
Defaults to None.
|
|
||||||
is_default_css: True if the CSS is defined in the Widget, False if the CSS is defined
|
is_default_css: True if the CSS is defined in the Widget, False if the CSS is defined
|
||||||
in a user stylesheet.
|
in a user stylesheet.
|
||||||
tie_breaker: Integer representing the priority of this source.
|
tie_breaker: Integer representing the priority of this source.
|
||||||
@@ -365,12 +364,12 @@ class Stylesheet:
|
|||||||
"""Apply the stylesheet to a DOM node.
|
"""Apply the stylesheet to a DOM node.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
node: The ``DOMNode`` to apply the stylesheet to.
|
node: The `DOMNode` to apply the stylesheet to.
|
||||||
Applies the styles defined in this ``Stylesheet`` to the node.
|
Applies the styles defined in this `Stylesheet` to the node.
|
||||||
If the same rule is defined multiple times for the node (e.g. multiple
|
If the same rule is defined multiple times for the node (e.g. multiple
|
||||||
classes modifying the same CSS property), then only the most specific
|
classes modifying the same CSS property), then only the most specific
|
||||||
rule will be applied.
|
rule will be applied.
|
||||||
animate: Animate changed rules. Defaults to ``False``.
|
animate: Animate changed rules.
|
||||||
"""
|
"""
|
||||||
# Dictionary of rule attribute names e.g. "text_background" to list of tuples.
|
# Dictionary of rule attribute names e.g. "text_background" to list of tuples.
|
||||||
# The tuples contain the rule specificity, and the value for that rule.
|
# The tuples contain the rule specificity, and the value for that rule.
|
||||||
@@ -447,7 +446,7 @@ class Stylesheet:
|
|||||||
Args:
|
Args:
|
||||||
node: A DOM node.
|
node: A DOM node.
|
||||||
rules: Mapping of rules.
|
rules: Mapping of rules.
|
||||||
animate: Enable animation. Defaults to False.
|
animate: Enable animation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Alias styles and base styles
|
# Alias styles and base styles
|
||||||
@@ -519,7 +518,7 @@ class Stylesheet:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
root: Root note to update.
|
root: Root note to update.
|
||||||
animate: Enable CSS animation. Defaults to False.
|
animate: Enable CSS animation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.update_nodes(root.walk_children(with_self=True), animate=animate)
|
self.update_nodes(root.walk_children(with_self=True), animate=animate)
|
||||||
@@ -529,7 +528,7 @@ class Stylesheet:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
nodes: Nodes to update.
|
nodes: Nodes to update.
|
||||||
animate: Enable CSS animation. Defaults to False.
|
animate: Enable CSS animation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
rules_map = self.rules_map
|
rules_map = self.rules_map
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class TokenError(Exception):
|
|||||||
code: The code being parsed.
|
code: The code being parsed.
|
||||||
start: Line number of the error.
|
start: Line number of the error.
|
||||||
message: A message associated with the error.
|
message: A message associated with the error.
|
||||||
end: End location of token, or None if not known. Defaults to None.
|
end: End location of token, or None if not known.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.path = path
|
self.path = path
|
||||||
|
|||||||
@@ -410,8 +410,8 @@ class DemoApp(App[None]):
|
|||||||
"""Save an SVG "screenshot". This action will save an SVG file containing the current contents of the screen.
|
"""Save an SVG "screenshot". This action will save an SVG file containing the current contents of the screen.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filename: Filename of screenshot, or None to auto-generate. Defaults to None.
|
filename: Filename of screenshot, or None to auto-generate.
|
||||||
path: Path to directory. Defaults to "./".
|
path: Path to directory.
|
||||||
"""
|
"""
|
||||||
self.bell()
|
self.bell()
|
||||||
path = self.save_screenshot(filename, path)
|
path = self.save_screenshot(filename, path)
|
||||||
|
|||||||
@@ -94,12 +94,6 @@ class ColorSystem:
|
|||||||
def generate(self) -> dict[str, str]:
|
def generate(self) -> dict[str, str]:
|
||||||
"""Generate a mapping of color name on to a CSS color.
|
"""Generate a mapping of color name on to a CSS color.
|
||||||
|
|
||||||
Args:
|
|
||||||
dark: Enable dark mode. Defaults to False.
|
|
||||||
luminosity_spread: Amount of luminosity to subtract and add to generate
|
|
||||||
shades. Defaults to 0.2.
|
|
||||||
text_alpha: Alpha value for text. Defaults to 0.9.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A mapping of color name on to a CSS-style encoded color
|
A mapping of color name on to a CSS-style encoded color
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
A DOMNode is a base class for any object within the Textual Document Object Model,
|
||||||
|
which includes all Widgets, Screens, and Apps.
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
@@ -25,7 +34,7 @@ from ._context import NoActiveAppError
|
|||||||
from ._node_list import NodeList
|
from ._node_list import NodeList
|
||||||
from ._types import WatchCallbackType
|
from ._types import WatchCallbackType
|
||||||
from ._worker_manager import WorkerManager
|
from ._worker_manager import WorkerManager
|
||||||
from .binding import Binding, Bindings, BindingType
|
from .binding import Binding, BindingType, _Bindings
|
||||||
from .color import BLACK, WHITE, Color
|
from .color import BLACK, WHITE, Color
|
||||||
from .css._error_tools import friendly_list
|
from .css._error_tools import friendly_list
|
||||||
from .css.constants import VALID_DISPLAY, VALID_VISIBILITY
|
from .css.constants import VALID_DISPLAY, VALID_VISIBILITY
|
||||||
@@ -134,7 +143,7 @@ class DOMNode(MessagePump):
|
|||||||
_css_type_names: ClassVar[frozenset[str]] = frozenset()
|
_css_type_names: ClassVar[frozenset[str]] = frozenset()
|
||||||
|
|
||||||
# Generated list of bindings
|
# Generated list of bindings
|
||||||
_merged_bindings: ClassVar[Bindings | None] = None
|
_merged_bindings: ClassVar[_Bindings | None] = None
|
||||||
|
|
||||||
_reactives: ClassVar[dict[str, Reactive]]
|
_reactives: ClassVar[dict[str, Reactive]]
|
||||||
|
|
||||||
@@ -168,7 +177,7 @@ class DOMNode(MessagePump):
|
|||||||
self._auto_refresh_timer: Timer | None = None
|
self._auto_refresh_timer: Timer | None = None
|
||||||
self._css_types = {cls.__name__ for cls in self._css_bases(self.__class__)}
|
self._css_types = {cls.__name__ for cls in self._css_bases(self.__class__)}
|
||||||
self._bindings = (
|
self._bindings = (
|
||||||
Bindings()
|
_Bindings()
|
||||||
if self._merged_bindings is None
|
if self._merged_bindings is None
|
||||||
else self._merged_bindings.copy()
|
else self._merged_bindings.copy()
|
||||||
)
|
)
|
||||||
@@ -191,7 +200,12 @@ class DOMNode(MessagePump):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def children(self) -> Sequence["Widget"]:
|
def children(self) -> Sequence["Widget"]:
|
||||||
"""A view on to the children."""
|
"""A view on to the children.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The node's children.
|
||||||
|
|
||||||
|
"""
|
||||||
return self._nodes
|
return self._nodes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -212,7 +226,7 @@ class DOMNode(MessagePump):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def workers(self) -> WorkerManager:
|
def workers(self) -> WorkerManager:
|
||||||
"""A worker manager."""
|
"""The app's worker manager. Shortcut for `self.app.workers`."""
|
||||||
return self.app.workers
|
return self.app.workers
|
||||||
|
|
||||||
def run_worker(
|
def run_worker(
|
||||||
@@ -346,27 +360,27 @@ class DOMNode(MessagePump):
|
|||||||
return classes
|
return classes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _merge_bindings(cls) -> Bindings:
|
def _merge_bindings(cls) -> _Bindings:
|
||||||
"""Merge bindings from base classes.
|
"""Merge bindings from base classes.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Merged bindings.
|
Merged bindings.
|
||||||
"""
|
"""
|
||||||
bindings: list[Bindings] = []
|
bindings: list[_Bindings] = []
|
||||||
|
|
||||||
for base in reversed(cls.__mro__):
|
for base in reversed(cls.__mro__):
|
||||||
if issubclass(base, DOMNode):
|
if issubclass(base, DOMNode):
|
||||||
if not base._inherit_bindings:
|
if not base._inherit_bindings:
|
||||||
bindings.clear()
|
bindings.clear()
|
||||||
bindings.append(
|
bindings.append(
|
||||||
Bindings(
|
_Bindings(
|
||||||
base.__dict__.get("BINDINGS", []),
|
base.__dict__.get("BINDINGS", []),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
keys: dict[str, Binding] = {}
|
keys: dict[str, Binding] = {}
|
||||||
for bindings_ in bindings:
|
for bindings_ in bindings:
|
||||||
keys.update(bindings_.keys)
|
keys.update(bindings_.keys)
|
||||||
return Bindings(keys.values())
|
return _Bindings(keys.values())
|
||||||
|
|
||||||
def _post_register(self, app: App) -> None:
|
def _post_register(self, app: App) -> None:
|
||||||
"""Called when the widget is registered
|
"""Called when the widget is registered
|
||||||
@@ -503,6 +517,7 @@ class DOMNode(MessagePump):
|
|||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
classes = _ClassesDescriptor()
|
classes = _ClassesDescriptor()
|
||||||
|
"""CSS class names for this node."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pseudo_classes(self) -> frozenset[str]:
|
def pseudo_classes(self) -> frozenset[str]:
|
||||||
@@ -584,9 +599,15 @@ class DOMNode(MessagePump):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def tree(self) -> Tree:
|
def tree(self) -> Tree:
|
||||||
"""Get a Rich tree object which will recursively render the structure of the node tree."""
|
"""Get a Rich tree object which will recursively render the structure of the node tree.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A Rich Tree renderable.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
def render_info(node: DOMNode) -> Pretty:
|
def render_info(node: DOMNode) -> Pretty:
|
||||||
|
"""Render a node for the tree."""
|
||||||
return Pretty(node)
|
return Pretty(node)
|
||||||
|
|
||||||
tree = Tree(render_info(self))
|
tree = Tree(render_info(self))
|
||||||
@@ -605,6 +626,9 @@ class DOMNode(MessagePump):
|
|||||||
def css_tree(self) -> Tree:
|
def css_tree(self) -> Tree:
|
||||||
"""Get a Rich tree object which will recursively render the structure of the node tree,
|
"""Get a Rich tree object which will recursively render the structure of the node tree,
|
||||||
which also displays CSS and size information.
|
which also displays CSS and size information.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A Rich Tree renderable.
|
||||||
"""
|
"""
|
||||||
from rich.columns import Columns
|
from rich.columns import Columns
|
||||||
from rich.console import Group
|
from rich.console import Group
|
||||||
@@ -613,6 +637,7 @@ class DOMNode(MessagePump):
|
|||||||
from .widget import Widget
|
from .widget import Widget
|
||||||
|
|
||||||
def render_info(node: DOMNode) -> Columns:
|
def render_info(node: DOMNode) -> Columns:
|
||||||
|
"""Render a node for the tree."""
|
||||||
if isinstance(node, Widget):
|
if isinstance(node, Widget):
|
||||||
info = Columns(
|
info = Columns(
|
||||||
[
|
[
|
||||||
@@ -659,7 +684,7 @@ class DOMNode(MessagePump):
|
|||||||
the child will also be bold.
|
the child will also be bold.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Rich Style object.
|
A Rich Style.
|
||||||
"""
|
"""
|
||||||
return Style.combine(
|
return Style.combine(
|
||||||
node.styles.text_style for node in reversed(self.ancestors_with_self)
|
node.styles.text_style for node in reversed(self.ancestors_with_self)
|
||||||
@@ -667,7 +692,12 @@ class DOMNode(MessagePump):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def rich_style(self) -> Style:
|
def rich_style(self) -> Style:
|
||||||
"""Get a Rich Style object for this DOMNode."""
|
"""Get a Rich Style object for this DOMNode.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A Rich style.
|
||||||
|
|
||||||
|
"""
|
||||||
background = Color(0, 0, 0, 0)
|
background = Color(0, 0, 0, 0)
|
||||||
color = Color(255, 255, 255, 0)
|
color = Color(255, 255, 255, 0)
|
||||||
style = Style()
|
style = Style()
|
||||||
@@ -720,6 +750,9 @@ class DOMNode(MessagePump):
|
|||||||
|
|
||||||
Note:
|
Note:
|
||||||
This is inclusive of ``self``.
|
This is inclusive of ``self``.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of nodes.
|
||||||
"""
|
"""
|
||||||
nodes: list[MessagePump | None] = []
|
nodes: list[MessagePump | None] = []
|
||||||
add_node = nodes.append
|
add_node = nodes.append
|
||||||
@@ -731,12 +764,22 @@ class DOMNode(MessagePump):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def ancestors(self) -> list[DOMNode]:
|
def ancestors(self) -> list[DOMNode]:
|
||||||
"""A list of ancestor nodes Nodes by tracing ancestors all the way back to App."""
|
"""A list of ancestor nodes Nodes by tracing ancestors all the way back to App.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of nodes.
|
||||||
|
|
||||||
|
"""
|
||||||
return self.ancestors_with_self[1:]
|
return self.ancestors_with_self[1:]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def displayed_children(self) -> list[Widget]:
|
def displayed_children(self) -> list[Widget]:
|
||||||
"""The children which don't have display: none set."""
|
"""The children which don't have display: none set.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of nodes.
|
||||||
|
|
||||||
|
"""
|
||||||
return [child for child in self._nodes if child.display]
|
return [child for child in self._nodes if child.display]
|
||||||
|
|
||||||
def watch(
|
def watch(
|
||||||
@@ -829,10 +872,9 @@ class DOMNode(MessagePump):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
filter_type: Filter only this type, or None for no filter.
|
filter_type: Filter only this type, or None for no filter.
|
||||||
Defaults to None.
|
with_self: Also yield self in addition to descendants.
|
||||||
with_self: Also yield self in addition to descendants. Defaults to False.
|
method: One of "depth" or "breadth".
|
||||||
method: One of "depth" or "breadth". Defaults to "depth".
|
reverse: Reverse the order (bottom up).
|
||||||
reverse: Reverse the order (bottom up). Defaults to False.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A list of nodes.
|
A list of nodes.
|
||||||
@@ -867,7 +909,7 @@ class DOMNode(MessagePump):
|
|||||||
"""Get a DOM query matching a selector.
|
"""Get a DOM query matching a selector.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
selector: A CSS selector or `None` for all nodes. Defaults to None.
|
selector: A CSS selector or `None` for all nodes.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A query object.
|
A query object.
|
||||||
@@ -902,7 +944,6 @@ class DOMNode(MessagePump):
|
|||||||
Args:
|
Args:
|
||||||
selector: A selector.
|
selector: A selector.
|
||||||
expect_type: Require the object be of the supplied type, or None for any type.
|
expect_type: Require the object be of the supplied type, or None for any type.
|
||||||
Defaults to None.
|
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
WrongType: If the wrong type was found.
|
WrongType: If the wrong type was found.
|
||||||
|
|||||||
@@ -1,3 +1,17 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
Builtin events sent by Textual.
|
||||||
|
|
||||||
|
Events may be marked as "Bubbles" and "Verbose".
|
||||||
|
See the [events guide](/guide/events/#bubbling) for an explanation of bubbling.
|
||||||
|
Verbose events are excluded from the textual console, unless you explicit request them with the `-v` switch as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
textual console -v
|
||||||
|
```
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Type, TypeVar
|
from typing import TYPE_CHECKING, Type, TypeVar
|
||||||
@@ -37,7 +51,12 @@ class Callback(Event, bubble=False, verbose=True):
|
|||||||
|
|
||||||
|
|
||||||
class InvokeCallbacks(Event, bubble=False, verbose=True):
|
class InvokeCallbacks(Event, bubble=False, verbose=True):
|
||||||
"""Sent after the Screen is updated"""
|
"""An internal event, sent to the screen to run callbacks.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ShutdownRequest(Event):
|
class ShutdownRequest(Event):
|
||||||
@@ -55,6 +74,8 @@ class Load(Event, bubble=False):
|
|||||||
Use this event to run any set up that doesn't require any visuals such as loading
|
Use this event to run any set up that doesn't require any visuals such as loading
|
||||||
configuration and binding keys.
|
configuration and binding keys.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -65,6 +86,9 @@ class Idle(Event, bubble=False):
|
|||||||
This is a pseudo-event in that it is created by the Textual system and doesn't go
|
This is a pseudo-event in that it is created by the Textual system and doesn't go
|
||||||
through the usual message queue.
|
through the usual message queue.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@@ -81,10 +105,14 @@ class Action(Event):
|
|||||||
|
|
||||||
class Resize(Event, bubble=False):
|
class Resize(Event, bubble=False):
|
||||||
"""Sent when the app or widget has been resized.
|
"""Sent when the app or widget has been resized.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
size: The new size of the Widget.
|
size: The new size of the Widget.
|
||||||
virtual_size: The virtual size (scrollable size) of the Widget.
|
virtual_size: The virtual size (scrollable size) of the Widget.
|
||||||
container_size: The size of the Widget's container widget. Defaults to None.
|
container_size: The size of the Widget's container widget.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -111,24 +139,47 @@ class Resize(Event, bubble=False):
|
|||||||
|
|
||||||
|
|
||||||
class Compose(Event, bubble=False, verbose=True):
|
class Compose(Event, bubble=False, verbose=True):
|
||||||
"""Sent to a widget to request it to compose and mount children."""
|
"""Sent to a widget to request it to compose and mount children.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Mount(Event, bubble=False, verbose=False):
|
class Mount(Event, bubble=False, verbose=False):
|
||||||
"""Sent when a widget is *mounted* and may receive messages."""
|
"""Sent when a widget is *mounted* and may receive messages.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Unmount(Mount, bubble=False, verbose=False):
|
class Unmount(Mount, bubble=False, verbose=False):
|
||||||
"""Sent when a widget is unmounted and may not longer receive messages."""
|
"""Sent when a widget is unmounted and may not longer receive messages.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Show(Event, bubble=False):
|
class Show(Event, bubble=False):
|
||||||
"""Sent when a widget has become visible."""
|
"""Sent when a widget has become visible.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Hide(Event, bubble=False):
|
class Hide(Event, bubble=False):
|
||||||
"""Sent when a widget has been hidden.
|
"""Sent when a widget has been hidden.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
A widget may be hidden by setting its `visible` flag to `False`, if it is no longer in a layout,
|
A widget may be hidden by setting its `visible` flag to `False`, if it is no longer in a layout,
|
||||||
or if it has been offset beyond the edges of the terminal.
|
or if it has been offset beyond the edges of the terminal.
|
||||||
|
|
||||||
@@ -136,15 +187,22 @@ class Hide(Event, bubble=False):
|
|||||||
|
|
||||||
|
|
||||||
class Ready(Event, bubble=False):
|
class Ready(Event, bubble=False):
|
||||||
"""Sent to the app when the DOM is ready."""
|
"""Sent to the app when the DOM is ready.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class MouseCapture(Event, bubble=False):
|
class MouseCapture(Event, bubble=False):
|
||||||
"""Sent when the mouse has been captured.
|
"""Sent when the mouse has been captured.
|
||||||
|
|
||||||
When a mouse has been captured, all further mouse events will be sent to the capturing widget.
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
When a mouse has been captured, all further mouse events will be sent to the capturing widget.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mouse_position: The position of the mouse when captured.
|
mouse_position: The position of the mouse when captured.
|
||||||
@@ -163,6 +221,9 @@ class MouseCapture(Event, bubble=False):
|
|||||||
class MouseRelease(Event, bubble=False):
|
class MouseRelease(Event, bubble=False):
|
||||||
"""Mouse has been released.
|
"""Mouse has been released.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mouse_position: The position of the mouse when released.
|
mouse_position: The position of the mouse when released.
|
||||||
"""
|
"""
|
||||||
@@ -183,6 +244,9 @@ class InputEvent(Event):
|
|||||||
class Key(InputEvent):
|
class Key(InputEvent):
|
||||||
"""Sent when the user hits a key on the keyboard.
|
"""Sent when the user hits a key on the keyboard.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: The key that was pressed.
|
key: The key that was pressed.
|
||||||
character: A printable character or ``None`` if it is not printable.
|
character: A printable character or ``None`` if it is not printable.
|
||||||
@@ -239,6 +303,9 @@ def _key_to_identifier(key: str) -> str:
|
|||||||
class MouseEvent(InputEvent, bubble=True):
|
class MouseEvent(InputEvent, bubble=True):
|
||||||
"""Sent in response to a mouse event.
|
"""Sent in response to a mouse event.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
x: The relative x coordinate.
|
x: The relative x coordinate.
|
||||||
y: The relative y coordinate.
|
y: The relative y coordinate.
|
||||||
@@ -395,35 +462,73 @@ class MouseEvent(InputEvent, bubble=True):
|
|||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class MouseMove(MouseEvent, bubble=False, verbose=True):
|
class MouseMove(MouseEvent, bubble=False, verbose=True):
|
||||||
"""Sent when the mouse cursor moves."""
|
"""Sent when the mouse cursor moves.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class MouseDown(MouseEvent, bubble=True, verbose=True):
|
class MouseDown(MouseEvent, bubble=True, verbose=True):
|
||||||
pass
|
"""Sent when a mouse button is pressed.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class MouseUp(MouseEvent, bubble=True, verbose=True):
|
class MouseUp(MouseEvent, bubble=True, verbose=True):
|
||||||
pass
|
"""Sent when a mouse button is released.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class MouseScrollDown(MouseEvent, bubble=True):
|
class MouseScrollDown(MouseEvent, bubble=True):
|
||||||
pass
|
"""Sent when the mouse wheel is scrolled *down*.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class MouseScrollUp(MouseEvent, bubble=True):
|
class MouseScrollUp(MouseEvent, bubble=True):
|
||||||
pass
|
"""Sent when the mouse wheel is scrolled *up*.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Click(MouseEvent, bubble=True):
|
class Click(MouseEvent, bubble=True):
|
||||||
pass
|
"""Sent when a widget is clicked.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class Timer(Event, bubble=False, verbose=True):
|
class Timer(Event, bubble=False, verbose=True):
|
||||||
|
"""Sent in response to a timer.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ["time", "count", "callback"]
|
__slots__ = ["time", "count", "callback"]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -445,27 +550,57 @@ class Timer(Event, bubble=False, verbose=True):
|
|||||||
|
|
||||||
|
|
||||||
class Enter(Event, bubble=False, verbose=True):
|
class Enter(Event, bubble=False, verbose=True):
|
||||||
pass
|
"""Sent when the mouse is moved over a widget.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Leave(Event, bubble=False, verbose=True):
|
class Leave(Event, bubble=False, verbose=True):
|
||||||
pass
|
"""Sent when the mouse is moved away from a widget.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Focus(Event, bubble=False):
|
class Focus(Event, bubble=False):
|
||||||
pass
|
"""Sent when a widget is focussed.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Blur(Event, bubble=False):
|
class Blur(Event, bubble=False):
|
||||||
pass
|
"""Sent when a widget is blurred (un-focussed).
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class DescendantFocus(Event, bubble=True, verbose=True):
|
class DescendantFocus(Event, bubble=True, verbose=True):
|
||||||
pass
|
"""Sent when a child widget is focussed.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class DescendantBlur(Event, bubble=True, verbose=True):
|
class DescendantBlur(Event, bubble=True, verbose=True):
|
||||||
pass
|
"""Sent when a child widget is blurred.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [X] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
@@ -475,6 +610,10 @@ class Paste(Event, bubble=True):
|
|||||||
bracketed paste mode. Textual will enable bracketed pastes when an app starts,
|
bracketed paste mode. Textual will enable bracketed pastes when an app starts,
|
||||||
and disable it when the app shuts down.
|
and disable it when the app shuts down.
|
||||||
|
|
||||||
|
- [X] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
text: The text that has been pasted.
|
text: The text that has been pasted.
|
||||||
"""
|
"""
|
||||||
@@ -488,8 +627,18 @@ class Paste(Event, bubble=True):
|
|||||||
|
|
||||||
|
|
||||||
class ScreenResume(Event, bubble=False):
|
class ScreenResume(Event, bubble=False):
|
||||||
pass
|
"""Sent to screen that has been made active.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ScreenSuspend(Event, bubble=False):
|
class ScreenSuspend(Event, bubble=False):
|
||||||
pass
|
"""Sent to screen when it is no longer active.
|
||||||
|
|
||||||
|
- [ ] Bubbles
|
||||||
|
- [ ] Verbose
|
||||||
|
|
||||||
|
"""
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ from typing import (
|
|||||||
cast,
|
cast,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from typing_extensions import Final
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing_extensions import TypeAlias
|
from typing_extensions import TypeAlias
|
||||||
|
|
||||||
@@ -31,7 +33,7 @@ T = TypeVar("T", int, float)
|
|||||||
|
|
||||||
|
|
||||||
def clamp(value: T, minimum: T, maximum: T) -> T:
|
def clamp(value: T, minimum: T, maximum: T) -> T:
|
||||||
"""Adjust a value to it is not less than a minimum and not greater
|
"""Adjust a value so it is not less than a minimum and not greater
|
||||||
than a maximum value.
|
than a maximum value.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -53,8 +55,9 @@ def clamp(value: T, minimum: T, maximum: T) -> T:
|
|||||||
|
|
||||||
|
|
||||||
class Offset(NamedTuple):
|
class Offset(NamedTuple):
|
||||||
"""A cell offset defined by x and y coordinates. Offsets are typically relative to the
|
"""A cell offset defined by x and y coordinates.
|
||||||
top left of the terminal or other container.
|
|
||||||
|
Offsets are typically relative to the top left of the terminal or other container.
|
||||||
|
|
||||||
Textual prefers the names `x` and `y`, but you could consider `x` to be the _column_ and `y` to be the _row_.
|
Textual prefers the names `x` and `y`, but you could consider `x` to be the _column_ and `y` to be the _row_.
|
||||||
|
|
||||||
@@ -67,21 +70,12 @@ class Offset(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_origin(self) -> bool:
|
def is_origin(self) -> bool:
|
||||||
"""Check if the point is at the origin (0, 0).
|
"""Is the offset at (0, 0)?"""
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if the offset is the origin.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self == (0, 0)
|
return self == (0, 0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def clamped(self) -> Offset:
|
def clamped(self) -> Offset:
|
||||||
"""Ensure x and y are above zero.
|
"""This offset with `x` and `y` restricted to values above zero."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
New offset.
|
|
||||||
"""
|
|
||||||
x, y = self
|
x, y = self
|
||||||
return Offset(0 if x < 0 else x, 0 if y < 0 else y)
|
return Offset(0 if x < 0 else x, 0 if y < 0 else y)
|
||||||
|
|
||||||
@@ -113,7 +107,7 @@ class Offset(NamedTuple):
|
|||||||
return Offset(-x, -y)
|
return Offset(-x, -y)
|
||||||
|
|
||||||
def blend(self, destination: Offset, factor: float) -> Offset:
|
def blend(self, destination: Offset, factor: float) -> Offset:
|
||||||
"""Blend (interpolate) to a new point.
|
"""Calculate a new offset on a line between this offset and a destination offset.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
destination: Point where factor would be 1.0.
|
destination: Point where factor would be 1.0.
|
||||||
@@ -159,31 +153,18 @@ class Size(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def area(self) -> int:
|
def area(self) -> int:
|
||||||
"""Get the area of the size.
|
"""The area occupied by a region of this size."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
Area in cells.
|
|
||||||
"""
|
|
||||||
return self.width * self.height
|
return self.width * self.height
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def region(self) -> Region:
|
def region(self) -> Region:
|
||||||
"""Get a region of the same size.
|
"""A region of the same size, at the origin."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
A region with the same size at (0, 0).
|
|
||||||
|
|
||||||
"""
|
|
||||||
width, height = self
|
width, height = self
|
||||||
return Region(0, 0, width, height)
|
return Region(0, 0, width, height)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def line_range(self) -> range:
|
def line_range(self) -> range:
|
||||||
"""Get a range covering lines.
|
"""A range object that covers values between 0 and `height`."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
A builtin range object.
|
|
||||||
"""
|
|
||||||
return range(self.height)
|
return range(self.height)
|
||||||
|
|
||||||
def __add__(self, other: object) -> Size:
|
def __add__(self, other: object) -> Size:
|
||||||
@@ -327,7 +308,7 @@ class Region(NamedTuple):
|
|||||||
Args:
|
Args:
|
||||||
window_region: The window region.
|
window_region: The window region.
|
||||||
region: The region to move inside the window.
|
region: The region to move inside the window.
|
||||||
top: Get offset to top of window. Defaults to False
|
top: Get offset to top of window.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
An offset required to add to region to move it inside window_region.
|
An offset required to add to region to move it inside window_region.
|
||||||
@@ -376,64 +357,43 @@ class Region(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def column_span(self) -> tuple[int, int]:
|
def column_span(self) -> tuple[int, int]:
|
||||||
"""Get the start and end columns (x coord).
|
"""A pair of integers for the start and end columns (x coordinates) in this region.
|
||||||
|
|
||||||
The end value is exclusive.
|
The end value is *exclusive*.
|
||||||
|
|
||||||
Returns:
|
|
||||||
Pair of x coordinates (column numbers).
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return (self.x, self.x + self.width)
|
return (self.x, self.x + self.width)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def line_span(self) -> tuple[int, int]:
|
def line_span(self) -> tuple[int, int]:
|
||||||
"""Get the start and end line number (y coord).
|
"""A pair of integers for the start and end lines (y coordinates) in this region.
|
||||||
|
|
||||||
The end value is exclusive.
|
The end value is *exclusive*.
|
||||||
|
|
||||||
Returns:
|
|
||||||
Pair of y coordinates (line numbers).
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return (self.y, self.y + self.height)
|
return (self.y, self.y + self.height)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def right(self) -> int:
|
def right(self) -> int:
|
||||||
"""Maximum X value (non inclusive).
|
"""Maximum X value (non inclusive)."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
x coordinate.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self.x + self.width
|
return self.x + self.width
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def bottom(self) -> int:
|
def bottom(self) -> int:
|
||||||
"""Maximum Y value (non inclusive).
|
"""Maximum Y value (non inclusive)."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
y coordinate.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self.y + self.height
|
return self.y + self.height
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def area(self) -> int:
|
def area(self) -> int:
|
||||||
"""Get the area within the region.
|
"""The are under the region."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
Area covered by this region.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self.width * self.height
|
return self.width * self.height
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def offset(self) -> Offset:
|
def offset(self) -> Offset:
|
||||||
"""Get the start point of the region.
|
"""The top left corner of the region.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Top left offset.
|
An offset.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return Offset(*self[:2])
|
return Offset(*self[:2])
|
||||||
@@ -443,8 +403,7 @@ class Region(NamedTuple):
|
|||||||
"""Bottom left offset of the region.
|
"""Bottom left offset of the region.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Bottom left offset.
|
An offset.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
x, y, _width, height = self
|
x, y, _width, height = self
|
||||||
return Offset(x, y + height)
|
return Offset(x, y + height)
|
||||||
@@ -454,7 +413,7 @@ class Region(NamedTuple):
|
|||||||
"""Top right offset of the region.
|
"""Top right offset of the region.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Top right.
|
An offset.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
x, y, width, _height = self
|
x, y, width, _height = self
|
||||||
@@ -462,10 +421,10 @@ class Region(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def bottom_right(self) -> Offset:
|
def bottom_right(self) -> Offset:
|
||||||
"""Bottom right of the region.
|
"""Bottom right offset of the region.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Bottom right.
|
An offset.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
x, y, width, height = self
|
x, y, width, height = self
|
||||||
@@ -473,21 +432,12 @@ class Region(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self) -> Size:
|
def size(self) -> Size:
|
||||||
"""Get the size of the region.
|
"""Get the size of the region."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
Size of the region.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return Size(*self[2:])
|
return Size(*self[2:])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def corners(self) -> tuple[int, int, int, int]:
|
def corners(self) -> tuple[int, int, int, int]:
|
||||||
"""Get the top left and bottom right coordinates as a tuple of integers.
|
"""The top left and bottom right coordinates as a tuple of four integers."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
A tuple of `(<left>, <top>, <right>, <bottom>)`.
|
|
||||||
"""
|
|
||||||
x, y, width, height = self
|
x, y, width, height = self
|
||||||
return x, y, x + width, y + height
|
return x, y, x + width, y + height
|
||||||
|
|
||||||
@@ -506,7 +456,7 @@ class Region(NamedTuple):
|
|||||||
"""An region of the same size at (0, 0).
|
"""An region of the same size at (0, 0).
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Reset region.
|
A region at the origin.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
_, _, width, height = self
|
_, _, width, height = self
|
||||||
@@ -897,63 +847,35 @@ class Spacing(NamedTuple):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def width(self) -> int:
|
def width(self) -> int:
|
||||||
"""Total space in width.
|
"""Total space in the x axis."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
Width.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self.left + self.right
|
return self.left + self.right
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def height(self) -> int:
|
def height(self) -> int:
|
||||||
"""Total space in height.
|
"""Total space in the y axis."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
Height.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self.top + self.bottom
|
return self.top + self.bottom
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def top_left(self) -> tuple[int, int]:
|
def top_left(self) -> tuple[int, int]:
|
||||||
"""Top left space.
|
"""A pair of integers for the left, and top space."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
`(<left>, <top>)`
|
|
||||||
|
|
||||||
"""
|
|
||||||
return (self.left, self.top)
|
return (self.left, self.top)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def bottom_right(self) -> tuple[int, int]:
|
def bottom_right(self) -> tuple[int, int]:
|
||||||
"""Bottom right space.
|
"""A pair of integers for the right, and bottom space."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
`(<right>, <bottom>)`
|
|
||||||
|
|
||||||
"""
|
|
||||||
return (self.right, self.bottom)
|
return (self.right, self.bottom)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def totals(self) -> tuple[int, int]:
|
def totals(self) -> tuple[int, int]:
|
||||||
"""Get total horizontal and vertical space.
|
"""A pair of integers for the total horizontal and vertical space."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
`(<horizontal>, <vertical>)`
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
top, right, bottom, left = self
|
top, right, bottom, left = self
|
||||||
return (left + right, top + bottom)
|
return (left + right, top + bottom)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def css(self) -> str:
|
def css(self) -> str:
|
||||||
"""Gets a string containing the spacing in CSS format.
|
"""A string containing the spacing in CSS format.
|
||||||
|
|
||||||
Returns:
|
|
||||||
Spacing in CSS format.
|
|
||||||
|
|
||||||
|
For example: "1" or "2 4" or "4 2 8 2".
|
||||||
"""
|
"""
|
||||||
top, right, bottom, left = self
|
top, right, bottom, left = self
|
||||||
if top == right == bottom == left:
|
if top == right == bottom == left:
|
||||||
@@ -1067,4 +989,5 @@ class Spacing(NamedTuple):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
NULL_OFFSET = Offset(0, 0)
|
NULL_OFFSET: Final = Offset(0, 0)
|
||||||
|
"""An Offset constant for (0, 0)."""
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
"""
|
||||||
|
A Textual Logging handler.
|
||||||
|
|
||||||
|
If there is an active Textual app, then log messages will go via the app (and logged via textual console).
|
||||||
|
|
||||||
|
If there is *no* active app, then log messages will go to stderr or stdout, depending on configuration.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from logging import Handler, LogRecord
|
from logging import Handler, LogRecord
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
The base class for all messages (including events).
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, ClassVar
|
from typing import TYPE_CHECKING, ClassVar
|
||||||
@@ -99,7 +106,7 @@ class Message:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
prevent: True if the default action should be suppressed,
|
prevent: True if the default action should be suppressed,
|
||||||
or False if the default actions should be performed. Defaults to True.
|
or False if the default actions should be performed.
|
||||||
"""
|
"""
|
||||||
self._no_default_action = prevent
|
self._no_default_action = prevent
|
||||||
return self
|
return self
|
||||||
@@ -108,7 +115,7 @@ class Message:
|
|||||||
"""Stop propagation of the message to parent.
|
"""Stop propagation of the message to parent.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stop: The stop flag. Defaults to True.
|
stop: The stop flag.
|
||||||
"""
|
"""
|
||||||
self._stop_propagation = stop
|
self._stop_propagation = stop
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
A message pump is a class that processes messages.
|
A message pump is a base class for any object which processes messages, which includes Widget, Screen, and App.
|
||||||
|
|
||||||
It is a base class for the App, Screen, and Widgets.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@@ -46,7 +44,7 @@ class MessagePumpClosed(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MessagePumpMeta(type):
|
class _MessagePumpMeta(type):
|
||||||
"""Metaclass for message pump. This exists to populate a Message inner class of a Widget with the
|
"""Metaclass for message pump. This exists to populate a Message inner class of a Widget with the
|
||||||
parent classes' name.
|
parent classes' name.
|
||||||
|
|
||||||
@@ -69,7 +67,7 @@ class MessagePumpMeta(type):
|
|||||||
return class_obj
|
return class_obj
|
||||||
|
|
||||||
|
|
||||||
class MessagePump(metaclass=MessagePumpMeta):
|
class MessagePump(metaclass=_MessagePumpMeta):
|
||||||
"""Base class which supplies a message pump."""
|
"""Base class which supplies a message pump."""
|
||||||
|
|
||||||
def __init__(self, parent: MessagePump | None = None) -> None:
|
def __init__(self, parent: MessagePump | None = None) -> None:
|
||||||
@@ -143,6 +141,7 @@ class MessagePump(metaclass=MessagePumpMeta):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def has_parent(self) -> bool:
|
def has_parent(self) -> bool:
|
||||||
|
"""Does this object have a parent?"""
|
||||||
return self._parent is not None
|
return self._parent is not None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -178,7 +177,7 @@ class MessagePump(metaclass=MessagePumpMeta):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_running(self) -> bool:
|
def is_running(self) -> bool:
|
||||||
"""Is the message pump running (potentially processing messages)."""
|
"""Is the message pump running (potentially processing messages)?"""
|
||||||
return self._running
|
return self._running
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -192,7 +191,7 @@ class MessagePump(metaclass=MessagePumpMeta):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_attached(self) -> bool:
|
def is_attached(self) -> bool:
|
||||||
"""Is the node is attached to the app via the DOM."""
|
"""Is the node is attached to the app via the DOM?"""
|
||||||
from .app import App
|
from .app import App
|
||||||
|
|
||||||
node = self
|
node = self
|
||||||
@@ -289,9 +288,9 @@ class MessagePump(metaclass=MessagePumpMeta):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
delay: Time to wait before invoking callback.
|
delay: Time to wait before invoking callback.
|
||||||
callback: Callback to call after time has expired. Defaults to None.
|
callback: Callback to call after time has expired.
|
||||||
name: Name of the timer (for debug). Defaults to None.
|
name: Name of the timer (for debug).
|
||||||
pause: Start timer paused. Defaults to False.
|
pause: Start timer paused.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A timer object.
|
A timer object.
|
||||||
@@ -321,10 +320,10 @@ class MessagePump(metaclass=MessagePumpMeta):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
interval: Time between calls.
|
interval: Time between calls.
|
||||||
callback: Function to call. Defaults to None.
|
callback: Function to call.
|
||||||
name: Name of the timer object. Defaults to None.
|
name: Name of the timer object.
|
||||||
repeat: Number of times to repeat the call or 0 for continuous. Defaults to 0.
|
repeat: Number of times to repeat the call or 0 for continuous.
|
||||||
pause: Start the timer paused. Defaults to False.
|
pause: Start the timer paused.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A timer object.
|
A timer object.
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
The pilot object is used by [App.run_test][textual.app.App.run_test] to programmatically operate an app.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
The `Reactive` class implements [reactivity](/guide/reactivity/).
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
@@ -33,11 +39,11 @@ class Reactive(Generic[ReactiveType]):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
default: A default value or callable that returns a default.
|
default: A default value or callable that returns a default.
|
||||||
layout: Perform a layout on change. Defaults to False.
|
layout: Perform a layout on change.
|
||||||
repaint: Perform a repaint on change. Defaults to True.
|
repaint: Perform a repaint on change.
|
||||||
init: Call watchers on initialize (post mount). Defaults to False.
|
init: Call watchers on initialize (post mount).
|
||||||
always_update: Call watchers even when the new value equals the old value. Defaults to False.
|
always_update: Call watchers even when the new value equals the old value.
|
||||||
compute: Run compute methods when attribute is changed. Defaults to True.
|
compute: Run compute methods when attribute is changed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_reactives: ClassVar[dict[str, object]] = {}
|
_reactives: ClassVar[dict[str, object]] = {}
|
||||||
@@ -280,10 +286,10 @@ class reactive(Reactive[ReactiveType]):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
default: A default value or callable that returns a default.
|
default: A default value or callable that returns a default.
|
||||||
layout: Perform a layout on change. Defaults to False.
|
layout: Perform a layout on change.
|
||||||
repaint: Perform a repaint on change. Defaults to True.
|
repaint: Perform a repaint on change.
|
||||||
init: Call watchers on initialize (post mount). Defaults to True.
|
init: Call watchers on initialize (post mount).
|
||||||
always_update: Call watchers even when the new value equals the old value. Defaults to False.
|
always_update: Call watchers even when the new value equals the old value.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -309,7 +315,7 @@ class var(Reactive[ReactiveType]):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
default: A default value or callable that returns a default.
|
default: A default value or callable that returns a default.
|
||||||
init: Call watchers on initialize (post mount). Defaults to True.
|
init: Call watchers on initialize (post mount).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -339,7 +345,7 @@ def _watch(
|
|||||||
obj: The parent object.
|
obj: The parent object.
|
||||||
attribute_name: The attribute to watch.
|
attribute_name: The attribute to watch.
|
||||||
callback: A callable to call when the attribute changes.
|
callback: A callable to call when the attribute changes.
|
||||||
init: True to call watcher initialization. Defaults to True.
|
init: True to call watcher initialization.
|
||||||
"""
|
"""
|
||||||
if not hasattr(obj, "__watchers"):
|
if not hasattr(obj, "__watchers"):
|
||||||
setattr(obj, "__watchers", {})
|
setattr(obj, "__watchers", {})
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class UnderlineBar:
|
|||||||
"""Thin horizontal bar with a portion highlighted.
|
"""Thin horizontal bar with a portion highlighted.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
highlight_range: The range to highlight. Defaults to ``(0, 0)`` (no highlight)
|
highlight_range: The range to highlight.
|
||||||
highlight_style: The style of the highlighted range of the bar.
|
highlight_style: The style of the highlighted range of the bar.
|
||||||
background_style: The style of the non-highlighted range(s) of the bar.
|
background_style: The style of the non-highlighted range(s) of the bar.
|
||||||
width: The width of the bar, or ``None`` to fill available width.
|
width: The width of the bar, or ``None`` to fill available width.
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
The `Screen` class is a special widget which represents the content in the terminal. See [Screens](/guide/screens/) for details.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Iterable, Iterator
|
from typing import TYPE_CHECKING, Iterable, Iterator
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
"""
|
||||||
|
`ScrollView` is a base class for [line api](/guide/widgets#line-api) widgets.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from rich.console import RenderableType
|
from rich.console import RenderableType
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
A Strip contains the result of rendering a widget.
|
||||||
|
See [line API](/guide/widgets#line-api) for how to use Strips.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
@@ -51,7 +57,7 @@ class Strip:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
segments: An iterable of segments.
|
segments: An iterable of segments.
|
||||||
cell_length: The cell length if known, or None to calculate on demand. Defaults to None.
|
cell_length: The cell length if known, or None to calculate on demand.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = [
|
__slots__ = [
|
||||||
@@ -117,7 +123,7 @@ class Strip:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
lines: List of lines, where a line is a list of segments.
|
lines: List of lines, where a line is a list of segments.
|
||||||
cell_length: Cell length of lines (must be same) or None if not known. Defaults to None.
|
cell_length: Cell length of lines (must be same) or None if not known.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of strips.
|
List of strips.
|
||||||
@@ -205,7 +211,7 @@ class Strip:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
cell_length: New desired cell length.
|
cell_length: New desired cell length.
|
||||||
style: Style when extending, or `None`. Defaults to `None`.
|
style: Style when extending, or `None`.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A new strip with the supplied cell length.
|
A new strip with the supplied cell length.
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ class Timer:
|
|||||||
Args:
|
Args:
|
||||||
event_target: The object which will receive the timer events.
|
event_target: The object which will receive the timer events.
|
||||||
interval: The time between timer events, in seconds.
|
interval: The time between timer events, in seconds.
|
||||||
name: A name to assign the event (for debugging). Defaults to None.
|
name: A name to assign the event (for debugging).
|
||||||
callback: A optional callback to invoke when the event is handled. Defaults to None.
|
callback: A optional callback to invoke when the event is handled.
|
||||||
repeat: The number of times to repeat the timer, or None to repeat forever. Defaults to None.
|
repeat: The number of times to repeat the timer, or None to repeat forever.
|
||||||
skip: Enable skipping of scheduled events that couldn't be sent in time. Defaults to True.
|
skip: Enable skipping of scheduled events that couldn't be sent in time.
|
||||||
pause: Start the timer paused. Defaults to False.
|
pause: Start the timer paused.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_timer_count: int = 1
|
_timer_count: int = 1
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
"""
|
||||||
|
Functions for *walking* the DOM.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
For most purposes you would be better off using [query][textual.dom.DOMNode.query], which uses these functions internally.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections import deque
|
from collections import deque
|
||||||
@@ -44,8 +53,7 @@ def walk_depth_first(
|
|||||||
Args:
|
Args:
|
||||||
root: The root note (starting point).
|
root: The root note (starting point).
|
||||||
filter_type: Optional DOMNode subclass to filter by, or ``None`` for no filter.
|
filter_type: Optional DOMNode subclass to filter by, or ``None`` for no filter.
|
||||||
Defaults to None.
|
with_root: Include the root in the walk.
|
||||||
with_root: Include the root in the walk. Defaults to True.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
An iterable of DOMNodes, or the type specified in ``filter_type``.
|
An iterable of DOMNodes, or the type specified in ``filter_type``.
|
||||||
@@ -106,8 +114,7 @@ def walk_breadth_first(
|
|||||||
Args:
|
Args:
|
||||||
root: The root note (starting point).
|
root: The root note (starting point).
|
||||||
filter_type: Optional DOMNode subclass to filter by, or ``None`` for no filter.
|
filter_type: Optional DOMNode subclass to filter by, or ``None`` for no filter.
|
||||||
Defaults to None.
|
with_root: Include the root in the walk.
|
||||||
with_root: Include the root in the walk. Defaults to True.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
An iterable of DOMNodes, or the type specified in ``filter_type``.
|
An iterable of DOMNodes, or the type specified in ``filter_type``.
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
"""
|
||||||
|
The base class for widgets.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from asyncio import Lock, wait
|
from asyncio import Lock, wait
|
||||||
@@ -84,10 +89,12 @@ _JUSTIFY_MAP: dict[str, JustifyMethod] = {
|
|||||||
|
|
||||||
|
|
||||||
class AwaitMount:
|
class AwaitMount:
|
||||||
"""An awaitable returned by mount() and mount_all().
|
"""An *optional* awaitable returned by [mount][textual.widget.Widget.mount] and [mount_all][textual.widget.Widget.mount_all].
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
```python
|
||||||
await self.mount(Static("foo"))
|
await self.mount(Static("foo"))
|
||||||
|
```
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -164,7 +171,7 @@ class _Styled:
|
|||||||
return Measurement.get(console, options, self.renderable)
|
return Measurement.get(console, options, self.renderable)
|
||||||
|
|
||||||
|
|
||||||
class RenderCache(NamedTuple):
|
class _RenderCache(NamedTuple):
|
||||||
"""Stores results of a previous render."""
|
"""Stores results of a previous render."""
|
||||||
|
|
||||||
size: Size
|
size: Size
|
||||||
@@ -286,6 +293,15 @@ class Widget(DOMNode):
|
|||||||
classes: str | None = None,
|
classes: str | None = None,
|
||||||
disabled: bool = False,
|
disabled: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""Initialize a Widget.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*children: Child widgets.
|
||||||
|
name: The name of the button.
|
||||||
|
id: The ID of the button in the DOM.
|
||||||
|
classes: The CSS classes of the button.
|
||||||
|
disabled: Whether the button is disabled or not.
|
||||||
|
"""
|
||||||
self._size = Size(0, 0)
|
self._size = Size(0, 0)
|
||||||
self._container_size = Size(0, 0)
|
self._container_size = Size(0, 0)
|
||||||
self._layout_required = False
|
self._layout_required = False
|
||||||
@@ -302,7 +318,7 @@ class Widget(DOMNode):
|
|||||||
self._border_title: Text | None = None
|
self._border_title: Text | None = None
|
||||||
self._border_subtitle: Text | None = None
|
self._border_subtitle: Text | None = None
|
||||||
|
|
||||||
self._render_cache = RenderCache(Size(0, 0), [])
|
self._render_cache = _RenderCache(Size(0, 0), [])
|
||||||
# Regions which need to be updated (in Widget)
|
# Regions which need to be updated (in Widget)
|
||||||
self._dirty_regions: set[Region] = set()
|
self._dirty_regions: set[Region] = set()
|
||||||
# Regions which need to be transferred from cache to screen
|
# Regions which need to be transferred from cache to screen
|
||||||
@@ -469,7 +485,6 @@ class Widget(DOMNode):
|
|||||||
Args:
|
Args:
|
||||||
id: The ID of the child.
|
id: The ID of the child.
|
||||||
expect_type: Require the object be of the supplied type, or None for any type.
|
expect_type: Require the object be of the supplied type, or None for any type.
|
||||||
Defaults to None.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The first child of this node with the ID.
|
The first child of this node with the ID.
|
||||||
@@ -1498,11 +1513,11 @@ class Widget(DOMNode):
|
|||||||
attribute: Name of the attribute to animate.
|
attribute: Name of the attribute to animate.
|
||||||
value: The value to animate to.
|
value: The value to animate to.
|
||||||
final_value: The final value of the animation. Defaults to `value` if not set.
|
final_value: The final value of the animation. Defaults to `value` if not set.
|
||||||
duration: The duration of the animate. Defaults to None.
|
duration: The duration of the animate.
|
||||||
speed: The speed of the animation. Defaults to None.
|
speed: The speed of the animation.
|
||||||
delay: A delay (in seconds) before the animation starts. Defaults to 0.0.
|
delay: A delay (in seconds) before the animation starts.
|
||||||
easing: An easing method. Defaults to "in_out_cubic".
|
easing: An easing method.
|
||||||
on_complete: A callable to invoke when the animation is finished. Defaults to None.
|
on_complete: A callable to invoke when the animation is finished.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self._animate is None:
|
if self._animate is None:
|
||||||
@@ -2663,7 +2678,7 @@ class Widget(DOMNode):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
strips = [Strip(line, width) for line in lines]
|
strips = [Strip(line, width) for line in lines]
|
||||||
self._render_cache = RenderCache(self.size, strips)
|
self._render_cache = _RenderCache(self.size, strips)
|
||||||
self._dirty_regions.clear()
|
self._dirty_regions.clear()
|
||||||
|
|
||||||
def render_line(self, y: int) -> Strip:
|
def render_line(self, y: int) -> Strip:
|
||||||
@@ -2886,7 +2901,7 @@ class Widget(DOMNode):
|
|||||||
When captured, mouse events will go to this widget even when the pointer is not directly over the widget.
|
When captured, mouse events will go to this widget even when the pointer is not directly over the widget.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
capture: True to capture or False to release. Defaults to True.
|
capture: True to capture or False to release.
|
||||||
"""
|
"""
|
||||||
self.app.capture_mouse(self if capture else None)
|
self.app.capture_mouse(self if capture else None)
|
||||||
|
|
||||||
|
|||||||
@@ -553,7 +553,7 @@ class Markdown(Widget):
|
|||||||
"""A Markdown widget.
|
"""A Markdown widget.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
markdown: String containing Markdown or None to leave blank for now. Defaults to None.
|
markdown: String containing Markdown or None to leave blank for now.
|
||||||
name: The name of the widget.
|
name: The name of the widget.
|
||||||
id: The ID of the widget in the DOM.
|
id: The ID of the widget in the DOM.
|
||||||
classes: The CSS classes of the widget.
|
classes: The CSS classes of the widget.
|
||||||
@@ -850,8 +850,8 @@ class MarkdownViewer(VerticalScroll, can_focus=True, can_focus_children=True):
|
|||||||
"""Create a Markdown Viewer object.
|
"""Create a Markdown Viewer object.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
markdown: String containing Markdown, or None to leave blank. Defaults to None.
|
markdown: String containing Markdown, or None to leave blank.
|
||||||
show_table_of_contents: Show a table of contents in a sidebar. Defaults to True.
|
show_table_of_contents: Show a table of contents in a sidebar.
|
||||||
name: The name of the widget.
|
name: The name of the widget.
|
||||||
id: The ID of the widget in the DOM.
|
id: The ID of the widget in the DOM.
|
||||||
classes: The CSS classes of the widget.
|
classes: The CSS classes of the widget.
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class Placeholder(Widget):
|
|||||||
label: The label to identify the placeholder.
|
label: The label to identify the placeholder.
|
||||||
If no label is present, uses the placeholder ID instead.
|
If no label is present, uses the placeholder ID instead.
|
||||||
variant: The variant of the placeholder.
|
variant: The variant of the placeholder.
|
||||||
name: The name of the placeholder. Defaults to None.
|
name: The name of the placeholder.
|
||||||
id: The ID of the placeholder in the DOM.
|
id: The ID of the placeholder in the DOM.
|
||||||
classes: A space separated string with the CSS classes
|
classes: A space separated string with the CSS classes
|
||||||
of the placeholder, if any.
|
of the placeholder, if any.
|
||||||
|
|||||||
@@ -29,13 +29,12 @@ class Static(Widget, inherit_bindings=False):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
renderable: A Rich renderable, or string containing console markup.
|
renderable: A Rich renderable, or string containing console markup.
|
||||||
Defaults to "".
|
expand: Expand content if required to fill container.
|
||||||
expand: Expand content if required to fill container. Defaults to False.
|
shrink: Shrink content if required to fill container.
|
||||||
shrink: Shrink content if required to fill container. Defaults to False.
|
markup: True if markup should be parsed and rendered.
|
||||||
markup: True if markup should be parsed and rendered. Defaults to True.
|
name: Name of widget.
|
||||||
name: Name of widget. Defaults to None.
|
id: ID of Widget.
|
||||||
id: ID of Widget. Defaults to None.
|
classes: Space separated list of class names.
|
||||||
classes: Space separated list of class names. Defaults to None.
|
|
||||||
disabled: Whether the static is disabled or not.
|
disabled: Whether the static is disabled or not.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ class Switch(Widget, can_focus=True):
|
|||||||
"""Initialise the switch.
|
"""Initialise the switch.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
value: The initial value of the switch. Defaults to False.
|
value: The initial value of the switch.
|
||||||
animate: True if the switch should animate when toggled. Defaults to True.
|
animate: True if the switch should animate when toggled.
|
||||||
name: The name of the switch.
|
name: The name of the switch.
|
||||||
id: The ID of the switch in the DOM.
|
id: The ID of the switch in the DOM.
|
||||||
classes: The CSS classes of the switch.
|
classes: The CSS classes of the switch.
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ class ToggleButton(Static, can_focus=True):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
label: The label for the toggle.
|
label: The label for the toggle.
|
||||||
value: The initial value of the toggle. Defaults to `False`.
|
value: The initial value of the toggle.
|
||||||
button_first: Should the button come before the label, or after?
|
button_first: Should the button come before the label, or after?
|
||||||
name: The name of the toggle.
|
name: The name of the toggle.
|
||||||
id: The ID of the toggle in the DOM.
|
id: The ID of the toggle in the DOM.
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user