mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
add render background
This commit is contained in:
@@ -33,6 +33,7 @@ from .geometry import Offset, Region, Size
|
||||
from .layouts.dock import Dock
|
||||
from .message_pump import MessagePump
|
||||
from .reactive import Reactive
|
||||
from .renderables.gradient import VerticalGradient
|
||||
from .view import View
|
||||
from .widget import Widget
|
||||
|
||||
@@ -152,9 +153,6 @@ class App(DOMNode):
|
||||
def __rich_repr__(self) -> rich.repr.Result:
|
||||
yield "title", self.title
|
||||
|
||||
def __rich__(self) -> RenderableType:
|
||||
return self.view
|
||||
|
||||
@property
|
||||
def animator(self) -> Animator:
|
||||
return self._animator
|
||||
@@ -287,6 +285,10 @@ class App(DOMNode):
|
||||
except EmptyQueryError:
|
||||
raise KeyError(selector)
|
||||
|
||||
def render_background(self) -> RenderableType:
|
||||
gradient = VerticalGradient("red", "blue")
|
||||
return gradient
|
||||
|
||||
def update_styles(self) -> None:
|
||||
"""Request update of styles.
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ from ..geometry import Spacing, SpacingDimensions, clamp
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..layout import Layout
|
||||
from .styles import Styles
|
||||
from .styles import Styles, StylesBase
|
||||
from .styles import DockGroup
|
||||
|
||||
from .._box import BoxType
|
||||
@@ -55,7 +55,7 @@ class ScalarProperty:
|
||||
self.name = name
|
||||
|
||||
def __get__(
|
||||
self, obj: Styles, objtype: type[Styles] | None = None
|
||||
self, obj: StylesBase, objtype: type[Styles] | None = None
|
||||
) -> Scalar | None:
|
||||
"""Get the scalar property
|
||||
|
||||
@@ -69,7 +69,7 @@ class ScalarProperty:
|
||||
value = obj.get_rule(self.name)
|
||||
return value
|
||||
|
||||
def __set__(self, obj: Styles, value: float | Scalar | str | None) -> None:
|
||||
def __set__(self, obj: StylesBase, value: float | Scalar | str | None) -> None:
|
||||
"""Set the scalar property
|
||||
|
||||
Args:
|
||||
@@ -116,14 +116,14 @@ class BoxProperty:
|
||||
|
||||
DEFAULT = ("", Color.default())
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
_type, edge = name.split("_")
|
||||
self._type = _type
|
||||
self.edge = edge
|
||||
|
||||
def __get__(
|
||||
self, obj: Styles, objtype: type[Styles] | None = None
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> tuple[BoxType, Color]:
|
||||
"""Get the box property
|
||||
|
||||
@@ -206,7 +206,7 @@ class Edges(NamedTuple):
|
||||
class BorderProperty:
|
||||
"""Descriptor for getting and setting full borders and outlines."""
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
self._properties = (
|
||||
f"{name}_top",
|
||||
@@ -215,7 +215,9 @@ class BorderProperty:
|
||||
f"{name}_left",
|
||||
)
|
||||
|
||||
def __get__(self, obj: Styles, objtype: type[Styles] | None = None) -> Edges:
|
||||
def __get__(
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> Edges:
|
||||
"""Get the border
|
||||
|
||||
Args:
|
||||
@@ -237,7 +239,7 @@ class BorderProperty:
|
||||
|
||||
def __set__(
|
||||
self,
|
||||
obj: Styles,
|
||||
obj: StylesBase,
|
||||
border: BorderDefinition | None,
|
||||
) -> None:
|
||||
"""Set the border
|
||||
@@ -298,7 +300,9 @@ class StyleProperty:
|
||||
|
||||
DEFAULT_STYLE = Style()
|
||||
|
||||
def __get__(self, obj: Styles, objtype: type[Styles] | None = None) -> Style:
|
||||
def __get__(
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> Style:
|
||||
"""Get the Style
|
||||
|
||||
Args:
|
||||
@@ -319,7 +323,7 @@ class StyleProperty:
|
||||
|
||||
return style
|
||||
|
||||
def __set__(self, obj: Styles, style: Style | str | None):
|
||||
def __set__(self, obj: StylesBase, style: Style | str | None):
|
||||
"""Set the Style
|
||||
|
||||
Args:
|
||||
@@ -352,10 +356,12 @@ class StyleProperty:
|
||||
class SpacingProperty:
|
||||
"""Descriptor for getting and setting spacing properties (e.g. padding and margin)."""
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj: Styles, objtype: type[Styles] | None = None) -> Spacing:
|
||||
def __get__(
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> Spacing:
|
||||
"""Get the Spacing
|
||||
|
||||
Args:
|
||||
@@ -367,7 +373,7 @@ class SpacingProperty:
|
||||
"""
|
||||
return obj.get_rule(self.name, NULL_SPACING)
|
||||
|
||||
def __set__(self, obj: Styles, spacing: SpacingDimensions | None):
|
||||
def __set__(self, obj: StylesBase, spacing: SpacingDimensions | None):
|
||||
"""Set the Spacing
|
||||
|
||||
Args:
|
||||
@@ -394,7 +400,7 @@ class DocksProperty:
|
||||
"""
|
||||
|
||||
def __get__(
|
||||
self, obj: Styles, objtype: type[Styles] | None = None
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> tuple[DockGroup, ...]:
|
||||
"""Get the Docks property
|
||||
|
||||
@@ -407,7 +413,7 @@ class DocksProperty:
|
||||
"""
|
||||
return obj.get_rule("docks", ())
|
||||
|
||||
def __set__(self, obj: Styles, docks: Iterable[DockGroup] | None):
|
||||
def __set__(self, obj: StylesBase, docks: Iterable[DockGroup] | None):
|
||||
"""Set the Docks property
|
||||
|
||||
Args:
|
||||
@@ -429,7 +435,7 @@ class DockProperty:
|
||||
the docks themselves, and where they are located on screen.
|
||||
"""
|
||||
|
||||
def __get__(self, obj: Styles, objtype: type[Styles] | None = None) -> str:
|
||||
def __get__(self, obj: StylesBase, objtype: type[StylesBase] | None = None) -> str:
|
||||
"""Get the Dock property
|
||||
|
||||
Args:
|
||||
@@ -455,11 +461,11 @@ class DockProperty:
|
||||
class LayoutProperty:
|
||||
"""Descriptor for getting and setting layout."""
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __get__(
|
||||
self, obj: Styles, objtype: type[Styles] | None = None
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> Layout | None:
|
||||
"""
|
||||
Args:
|
||||
@@ -470,7 +476,7 @@ class LayoutProperty:
|
||||
"""
|
||||
return obj.get_rule(self.name)
|
||||
|
||||
def __set__(self, obj: Styles, layout: str | Layout | None):
|
||||
def __set__(self, obj: StylesBase, layout: str | Layout | None):
|
||||
"""
|
||||
Args:
|
||||
obj (Styles): The Styles object.
|
||||
@@ -497,10 +503,12 @@ class OffsetProperty:
|
||||
will be adjusted by before it is rendered.
|
||||
"""
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj: Styles, objtype: type[Styles] | None = None) -> ScalarOffset:
|
||||
def __get__(
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> ScalarOffset:
|
||||
"""Get the offset
|
||||
|
||||
Args:
|
||||
@@ -514,7 +522,7 @@ class OffsetProperty:
|
||||
return obj.get_rule(self.name, ScalarOffset.null())
|
||||
|
||||
def __set__(
|
||||
self, obj: Styles, offset: tuple[int | str, int | str] | ScalarOffset | None
|
||||
self, obj: StylesBase, offset: tuple[int | str, int | str] | ScalarOffset | None
|
||||
):
|
||||
"""Set the offset
|
||||
|
||||
@@ -562,10 +570,10 @@ class StringEnumProperty:
|
||||
self._valid_values = valid_values
|
||||
self._default = default
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj: Styles, objtype: type[Styles] | None = None) -> str:
|
||||
def __get__(self, obj: StylesBase, objtype: type[StylesBase] | None = None) -> str:
|
||||
"""Get the string property, or the default value if it's not set
|
||||
|
||||
Args:
|
||||
@@ -577,7 +585,7 @@ class StringEnumProperty:
|
||||
"""
|
||||
return obj.get_rule(self.name, self._default)
|
||||
|
||||
def __set__(self, obj: Styles, value: str | None = None):
|
||||
def __set__(self, obj: StylesBase, value: str | None = None):
|
||||
"""Set the string property and ensure it is in the set of allowed values.
|
||||
|
||||
Args:
|
||||
@@ -603,10 +611,10 @@ class StringEnumProperty:
|
||||
class NameProperty:
|
||||
"""Descriptor for getting and setting name properties."""
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj: Styles, objtype: type[Styles] | None) -> str:
|
||||
def __get__(self, obj: StylesBase, objtype: type[StylesBase] | None) -> str:
|
||||
"""Get the name property
|
||||
|
||||
Args:
|
||||
@@ -618,7 +626,7 @@ class NameProperty:
|
||||
"""
|
||||
return obj.get_rule(self.name, "")
|
||||
|
||||
def __set__(self, obj: Styles, name: str | None):
|
||||
def __set__(self, obj: StylesBase, name: str | None):
|
||||
"""Set the name property
|
||||
|
||||
Args:
|
||||
@@ -640,16 +648,16 @@ class NameProperty:
|
||||
|
||||
|
||||
class NameListProperty:
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __get__(
|
||||
self, obj: Styles, objtype: type[Styles] | None = None
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> tuple[str, ...]:
|
||||
return obj.get_rule(self.name, ())
|
||||
|
||||
def __set__(
|
||||
self, obj: Styles, names: str | tuple[str] | None = None
|
||||
self, obj: StylesBase, names: str | tuple[str] | None = None
|
||||
) -> str | tuple[str] | None:
|
||||
|
||||
if names is None:
|
||||
@@ -668,10 +676,12 @@ class NameListProperty:
|
||||
class ColorProperty:
|
||||
"""Descriptor for getting and setting color properties."""
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj: Styles, objtype: type[Styles] | None = None) -> Color:
|
||||
def __get__(
|
||||
self, obj: StylesBaseStylesBase, objtype: type[Styles] | None = None
|
||||
) -> Color:
|
||||
"""Get the ``Color``, or ``Color.default()`` if no color is set.
|
||||
|
||||
Args:
|
||||
@@ -683,7 +693,7 @@ class ColorProperty:
|
||||
"""
|
||||
return obj.get_rule(self.name) or Color.default()
|
||||
|
||||
def __set__(self, obj: Styles, color: Color | str | None):
|
||||
def __set__(self, obj: StylesBase, color: Color | str | None):
|
||||
"""Set the Color
|
||||
|
||||
Args:
|
||||
@@ -727,7 +737,9 @@ class StyleFlagsProperty:
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj: Styles, objtype: type[Styles] | None = None) -> Style:
|
||||
def __get__(
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> Style:
|
||||
"""Get the ``Style``
|
||||
|
||||
Args:
|
||||
@@ -739,7 +751,7 @@ class StyleFlagsProperty:
|
||||
"""
|
||||
return obj.get_rule(self.name, Style.null())
|
||||
|
||||
def __set__(self, obj: Styles, style_flags: Style | str | None):
|
||||
def __set__(self, obj: StylesBase, style_flags: Style | str | None):
|
||||
"""Set the style using a style flag string
|
||||
|
||||
Args:
|
||||
@@ -774,7 +786,7 @@ class TransitionsProperty:
|
||||
"""Descriptor for getting transitions properties"""
|
||||
|
||||
def __get__(
|
||||
self, obj: Styles, objtype: type[Styles] | None = None
|
||||
self, obj: StylesBase, objtype: type[StylesBase] | None = None
|
||||
) -> dict[str, Transition]:
|
||||
"""Get a mapping of properties to the transitions applied to them.
|
||||
|
||||
@@ -804,10 +816,10 @@ class FractionalProperty:
|
||||
def __init__(self, default: float = 1.0):
|
||||
self.default = default
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
def __set_name__(self, owner: StylesBase, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj: Styles, type: type[Styles]) -> float:
|
||||
def __get__(self, obj: StylesBase, type: type[StylesBase]) -> float:
|
||||
"""Get the property value as a float between 0 and 1
|
||||
|
||||
Args:
|
||||
@@ -819,7 +831,7 @@ class FractionalProperty:
|
||||
"""
|
||||
return cast(float, obj.get_rule(self.name, self.default))
|
||||
|
||||
def __set__(self, obj: Styles, value: float | str | None) -> None:
|
||||
def __set__(self, obj: StylesBase, value: float | str | None) -> None:
|
||||
"""Set the property value, clamping it between 0 and 1.
|
||||
|
||||
Args:
|
||||
|
||||
@@ -162,6 +162,16 @@ class StylesBase(ABC):
|
||||
return NotImplemented
|
||||
return self.get_rules() == styles.get_rules()
|
||||
|
||||
@property
|
||||
def gutter(self) -> Spacing:
|
||||
"""Get space around widget.
|
||||
|
||||
Returns:
|
||||
Spacing: Space around widget.
|
||||
"""
|
||||
|
||||
return self.margin
|
||||
|
||||
@abstractmethod
|
||||
def has_rule(self, rule: str) -> bool:
|
||||
"""Check if a rule is set on this Styles object.
|
||||
|
||||
@@ -75,18 +75,19 @@ class DockLayout(Layout):
|
||||
|
||||
def make_dock_options(widget, edge: Edge) -> DockOptions:
|
||||
styles = widget.styles
|
||||
has_rule = styles.has_rule
|
||||
|
||||
return (
|
||||
DockOptions(
|
||||
styles.width.cells if styles.has_rule("width") else None,
|
||||
styles.width.fraction if styles.has_rule("width") else 1,
|
||||
styles.min_width.cells if styles.has_rule("min_width") else 1,
|
||||
styles.width.cells if has_rule("width") else None,
|
||||
styles.width.fraction if has_rule("width") else 1,
|
||||
styles.min_width.cells if has_rule("min_width") else 1,
|
||||
)
|
||||
if edge in ("left", "right")
|
||||
else DockOptions(
|
||||
styles.height.cells if styles.has_rule("height") else None,
|
||||
styles.height.fraction if styles.has_rule("height") else 1,
|
||||
styles.min_height.cells if styles.has_rule("min_height") else 1,
|
||||
styles.height.cells if has_rule("height") else None,
|
||||
styles.height.fraction if has_rule("height") else 1,
|
||||
styles.min_height.cells if has_rule("min_height") else 1,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from asyncio import Event
|
||||
from time import monotonic
|
||||
from typing import ClassVar
|
||||
|
||||
|
||||
@@ -21,3 +21,26 @@ def blend_colors(color1: Color, color2: Color, ratio: float) -> Color:
|
||||
return Color.from_rgb(
|
||||
red=r1 + dr * ratio, green=g1 + dg * ratio, blue=b1 + db * ratio
|
||||
)
|
||||
|
||||
|
||||
def blend_colors_rgb(
|
||||
color1: tuple[int, int, int], color2: tuple[int, int, int], ratio: float
|
||||
) -> Color:
|
||||
"""Blend two colors given as a tuple of 3 values for red, green, and blue.
|
||||
|
||||
Args:
|
||||
color1 (tuple[int, int, int]): The first color.
|
||||
color2 (tuple[int, int, int]): The second color.
|
||||
ratio (float): The ratio of color1 to color2.
|
||||
|
||||
Returns:
|
||||
Color: A Color representing the blending of the two supplied colors.
|
||||
"""
|
||||
r1, g1, b1 = color1
|
||||
r2, g2, b2 = color2
|
||||
dr = r2 - r1
|
||||
dg = g2 - g1
|
||||
db = b2 - b1
|
||||
return Color.from_rgb(
|
||||
red=r1 + dr * ratio, green=g1 + dg * ratio, blue=b1 + db * ratio
|
||||
)
|
||||
|
||||
@@ -204,17 +204,6 @@ class Widget(DOMNode):
|
||||
assert self._animate is not None
|
||||
return self._animate
|
||||
|
||||
@property
|
||||
def gutter(self) -> Spacing:
|
||||
"""Get additional space reserved by margin / padding / border.
|
||||
|
||||
Returns:
|
||||
Spacing: [description]
|
||||
"""
|
||||
styles = self.styles
|
||||
gutter = styles.margin + styles.padding + styles.border.spacing
|
||||
return gutter
|
||||
|
||||
def on_style_change(self) -> None:
|
||||
self.clear_render_cache()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user