changelog

This commit is contained in:
Will McGugan
2023-02-20 16:16:10 +00:00
parent be850635c2
commit 347b94a0fe
8 changed files with 82 additions and 25 deletions

View File

@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
### Changed
- Added alternative method of composing Widgets
## [0.11.1] - 2023-02-17
### Fixed

View File

@@ -38,10 +38,9 @@ class CodeBrowser(App):
"""Compose our UI."""
path = "./" if len(sys.argv) < 2 else sys.argv[1]
yield Header()
yield Container(
DirectoryTree(path, id="tree-view"),
Vertical(Static(id="code", expand=True), id="code-view"),
)
with Container():
yield DirectoryTree(path, id="tree-view")
yield Vertical(Static(id="code", expand=True), id="code-view")
yield Footer()
def on_mount(self, event: events.Mount) -> None:

32
src/textual/_compose.py Normal file
View File

@@ -0,0 +1,32 @@
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .app import App
from .widget import Widget
def compose(node: App | Widget) -> list[Widget]:
"""Compose child widgets.
Args:
node: The parent node.
Returns:
A list of widgets.
"""
app = node.app
nodes: list[Widget] = []
for child in node.compose():
if app._composed:
nodes.extend(app._composed)
app._composed.clear()
if app._compose_stack:
app._compose_stack[-1]._nodes._append(child)
else:
nodes.append(child)
if app._composed:
nodes.extend(app._composed)
app._composed.clear()
return nodes

View File

@@ -46,6 +46,7 @@ from ._animator import DEFAULT_EASING, Animatable, Animator, EasingFunction
from ._ansi_sequences import SYNC_END, SYNC_START
from ._asyncio import create_task
from ._callback import invoke
from ._compose import compose
from ._context import active_app
from ._event_broker import NoHandler, extract_handler_actions
from ._path import _make_path_object_relative
@@ -388,6 +389,9 @@ class App(Generic[ReturnType], DOMNode):
self._installed_screens: dict[str, Screen | Callable[[], Screen]] = {}
self._installed_screens.update(**self.SCREENS)
self._compose_stack: list[Widget] = []
self._composed: list[Widget] = []
self.devtools: DevtoolsClient | None = None
if "devtools" in self.features:
try:
@@ -1606,7 +1610,7 @@ class App(Generic[ReturnType], DOMNode):
async def _on_compose(self) -> None:
try:
widgets = list(self.compose())
widgets = compose(self)
except TypeError as error:
raise TypeError(
f"{self!r} compose() returned an invalid response; {error}"

View File

@@ -41,18 +41,16 @@ class ColorsView(Vertical):
]
for color_name in ColorSystem.COLOR_NAMES:
items: list[Widget] = [Label(f'"{color_name}"')]
for level in LEVELS:
color = f"{color_name}-{level}" if level else color_name
item = ColorItem(
ColorBar(f"${color}", classes="text label"),
ColorBar("$text-muted", classes="muted"),
ColorBar("$text-disabled", classes="disabled"),
classes=color,
)
items.append(item)
yield ColorGroup(*items, id=f"group-{color_name}")
with ColorGroup(id=f"group-{color_name}"):
yield Label(f'"{color_name}"')
for level in LEVELS:
color = f"{color_name}-{level}" if level else color_name
yield ColorItem(
ColorBar(f"${color}", classes="text label"),
ColorBar("$text-muted", classes="muted"),
ColorBar("$text-disabled", classes="disabled"),
classes=color,
)
class ColorsApp(App):

View File

@@ -73,16 +73,15 @@ class EasingApp(App):
)
yield EasingButtons()
yield Vertical(
Horizontal(
with Vertical():
yield Horizontal(
Label("Animation Duration:", id="label"), duration_input, id="inputs"
),
Horizontal(
)
yield Horizontal(
self.animated_bar,
Container(self.opacity_widget, id="other"),
),
Footer(),
)
)
yield Footer()
def on_button_pressed(self, event: Button.Pressed) -> None:
self.bell()

View File

@@ -134,6 +134,7 @@ class DOMNode(MessagePump):
self._classes.update(_classes)
self._nodes: NodeList = NodeList()
self._composing: bool = False
self._css_styles: Styles = Styles(self)
self._inline_styles: Styles = Styles(self)
self.styles: RenderStyles = RenderStyles(

View File

@@ -5,6 +5,7 @@ from collections import Counter
from fractions import Fraction
from itertools import islice
from operator import attrgetter
from types import TracebackType
from typing import (
TYPE_CHECKING,
ClassVar,
@@ -38,6 +39,7 @@ from . import errors, events, messages
from ._animator import DEFAULT_EASING, Animatable, BoundAnimator, EasingFunction
from ._arrange import DockArrangeResult, arrange
from ._asyncio import create_task
from ._compose import compose
from ._context import active_app
from ._easing import DEFAULT_SCROLL_EASING
from ._layout import Layout
@@ -363,6 +365,22 @@ class Widget(DOMNode):
def offset(self, offset: Offset) -> None:
self.styles.offset = ScalarOffset.from_offset(offset)
def __enter__(self) -> None:
self.app._compose_stack.append(self)
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None:
compose_stack = self.app._compose_stack
composed = compose_stack.pop()
if compose_stack:
compose_stack[-1]._nodes._append(composed)
else:
self.app._composed.append(composed)
ExpectType = TypeVar("ExpectType", bound="Widget")
@overload
@@ -2444,7 +2462,7 @@ class Widget(DOMNode):
async def _on_compose(self) -> None:
try:
widgets = list(self.compose())
widgets = compose(self)
except TypeError as error:
raise TypeError(
f"{self!r} compose() returned an invalid response; {error}"