Add style param to Widget render method

This commit is contained in:
Darren Burns
2022-05-05 16:06:49 +01:00
parent b2553b34b2
commit e473e4873a
21 changed files with 56 additions and 47 deletions

View File

@@ -10,7 +10,7 @@ class Clock(Widget):
def on_mount(self): def on_mount(self):
self.set_interval(1, self.refresh) self.set_interval(1, self.refresh)
def render(self): def render(self, styles: Styles):
time = datetime.now().strftime("%c") time = datetime.now().strftime("%c")
return Align.center(time, vertical="middle") return Align.center(time, vertical="middle")

View File

@@ -9,7 +9,7 @@ class Hover(Widget):
mouse_over = Reactive(False) mouse_over = Reactive(False)
def render(self) -> Panel: def render(self, styles: Styles) -> Panel:
return Panel("Hello [b]World[/b]", style=("on red" if self.mouse_over else "")) return Panel("Hello [b]World[/b]", style=("on red" if self.mouse_over else ""))
def on_enter(self) -> None: def on_enter(self) -> None:

View File

@@ -53,12 +53,12 @@ lorem = Text.from_markup(
class TweetHeader(Widget): class TweetHeader(Widget):
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return Text("Lorem Impsum", justify="center") return Text("Lorem Impsum", justify="center")
class TweetBody(Widget): class TweetBody(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return lorem return lorem
@@ -67,22 +67,22 @@ class Tweet(Widget):
class OptionItem(Widget): class OptionItem(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return Text("Option") return Text("Option")
class Error(Widget): class Error(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return Text("This is an error message", justify="center") return Text("This is an error message", justify="center")
class Warning(Widget): class Warning(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return Text("This is a warning message", justify="center") return Text("This is a warning message", justify="center")
class Success(Widget): class Success(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return Text("This is a success message", justify="center") return Text("This is a success message", justify="center")

View File

@@ -15,12 +15,12 @@ lorem = Text.from_markup(
class Lorem(Widget): class Lorem(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return Padding(lorem, 1) return Padding(lorem, 1)
class Background(Widget): class Background(Widget):
def render(self): def render(self, styles: Styles):
return VerticalGradient("#212121", "#212121") return VerticalGradient("#212121", "#212121")

View File

@@ -55,7 +55,7 @@ class Numbers(Widget):
value = Reactive("0") value = Reactive("0")
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
"""Build a Rich renderable to render the calculator display.""" """Build a Rich renderable to render the calculator display."""
return Padding( return Padding(
Align.right(FigletText(self.value), vertical="middle"), Align.right(FigletText(self.value), vertical="middle"),

View File

@@ -6,7 +6,7 @@ from textual.widgets import Static
class Thing(Widget): class Thing(Widget):
def render(self): def render(self, styles: Styles):
return "Hello, 3434 World.\n[b]Lorem impsum." return "Hello, 3434 World.\n[b]Lorem impsum."

View File

@@ -50,12 +50,12 @@ lorem = Text.from_markup(
class TweetHeader(Widget): class TweetHeader(Widget):
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return Text("Lorem Impsum", justify="center") return Text("Lorem Impsum", justify="center")
class TweetBody(Widget): class TweetBody(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return lorem return lorem
@@ -64,22 +64,22 @@ class Tweet(Widget):
class OptionItem(Widget): class OptionItem(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return Text("Option") return Text("Option")
class Error(Widget): class Error(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return Text("This is an error message", justify="center") return Text("This is an error message", justify="center")
class Warning(Widget): class Warning(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return Text("This is a warning message", justify="center") return Text("This is a warning message", justify="center")
class Success(Widget): class Success(Widget):
def render(self) -> Text: def render(self, styles: Styles) -> Text:
return Text("This is a success message", justify="center") return Text("This is a success message", justify="center")

View File

@@ -6,7 +6,7 @@ from textual.widget import Widget
class PanelWidget(Widget): class PanelWidget(Widget):
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return Panel("hello world!", title="Title") return Panel("hello world!", title="Title")

View File

@@ -11,7 +11,7 @@ from textual.widgets.tabs import Tabs, Tab
class Hr(Widget): class Hr(Widget):
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return Rule() return Rule()
@@ -22,7 +22,7 @@ class Info(Widget):
super().__init__() super().__init__()
self.text = text self.text = text
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return Padding(f"{self.text}", pad=(0, 1)) return Padding(f"{self.text}", pad=(0, 1))

View File

@@ -468,7 +468,7 @@ class App(Generic[ReturnType], DOMNode):
self.stylesheet.update(self) self.stylesheet.update(self)
self.screen.refresh(layout=True) self.screen.refresh(layout=True)
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return "" return ""
def query(self, selector: str | None = None) -> DOMQuery: def query(self, selector: str | None = None) -> DOMQuery:

View File

@@ -38,7 +38,7 @@ class Screen(Widget):
def watch_dark(self, dark: bool) -> None: def watch_dark(self, dark: bool) -> None:
pass pass
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return self.app.render() return self.app.render()
def get_offset(self, widget: Widget) -> Offset: def get_offset(self, widget: Widget) -> Offset:

View File

@@ -8,6 +8,7 @@ from rich.console import ConsoleOptions, RenderResult, RenderableType
from rich.segment import Segment, Segments from rich.segment import Segment, Segments
from rich.style import Style, StyleType from rich.style import Style, StyleType
from textual.css.styles import Styles
from textual.reactive import Reactive from textual.reactive import Reactive
from . import events from . import events
from ._types import MessageTarget from ._types import MessageTarget
@@ -205,7 +206,7 @@ class ScrollBar(Widget):
yield "window_size", self.window_size yield "window_size", self.window_size
yield "position", self.position yield "position", self.position
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
styles = self.parent.styles styles = self.parent.styles
style = Style( style = Style(
bgcolor=( bgcolor=(

View File

@@ -26,6 +26,7 @@ from .box_model import BoxModel, get_box_model
from .color import Color from .color import Color
from ._context import active_app from ._context import active_app
from ._types import Lines from ._types import Lines
from .css.styles import Styles
from .dom import DOMNode from .dom import DOMNode
from .geometry import clamp, Offset, Region, Size from .geometry import clamp, Offset, Region, Size
from .message import Message from .message import Message
@@ -156,7 +157,7 @@ class Widget(DOMNode):
int: The optimal width of the content. int: The optimal width of the content.
""" """
console = self.app.console console = self.app.console
renderable = self.render() renderable = self.render(self.styles)
measurement = Measurement.get(console, console.options, renderable) measurement = Measurement.get(console, console.options, renderable)
return measurement.maximum return measurement.maximum
@@ -173,7 +174,7 @@ class Widget(DOMNode):
Returns: Returns:
int: The height of the content. int: The height of the content.
""" """
renderable = self.render() renderable = self.render(self.styles)
options = self.console.options.update_width(width) options = self.console.options.update_width(width)
segments = self.console.render(renderable, options) segments = self.console.render(renderable, options)
# Cheaper than counting the lines returned from render_lines! # Cheaper than counting the lines returned from render_lines!
@@ -461,7 +462,7 @@ class Widget(DOMNode):
RenderableType: A new renderable. RenderableType: A new renderable.
""" """
renderable = self.render() renderable = self.render(self.styles)
styles = self.styles styles = self.styles
parent_styles = self.parent.styles parent_styles = self.parent.styles
@@ -661,9 +662,12 @@ class Widget(DOMNode):
self.set_dirty() self.set_dirty()
self.check_idle() self.check_idle()
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
"""Get renderable for widget. """Get renderable for widget.
Args:
styles (Styles): The Styles object for this Widget.
Returns: Returns:
RenderableType: Any renderable RenderableType: Any renderable
""" """

View File

@@ -6,6 +6,7 @@ from rich.console import RenderableType
from rich.text import Text from rich.text import Text
from .. import events from .. import events
from ..css.styles import Styles
from ..message import Message from ..message import Message
from ..reactive import Reactive from ..reactive import Reactive
from ..widget import Widget from ..widget import Widget
@@ -70,7 +71,7 @@ class Button(Widget, can_focus=True):
return Text.from_markup(label) return Text.from_markup(label)
return label return label
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return self.label return self.label
async def on_click(self, event: events.Click) -> None: async def on_click(self, event: events.Click) -> None:

View File

@@ -6,6 +6,7 @@ from rich.text import Text
import rich.repr import rich.repr
from .. import events from .. import events
from ..css.styles import Styles
from ..reactive import Reactive from ..reactive import Reactive
from ..widget import Widget from ..widget import Widget
@@ -59,7 +60,7 @@ class Footer(Widget):
text.append_text(key_text) text.append_text(key_text)
return text return text
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
if self._key_text is None: if self._key_text is None:
self._key_text = self.make_key_text() self._key_text = self.make_key_text()
return self._key_text return self._key_text

View File

@@ -10,6 +10,7 @@ from rich.style import StyleType
from rich.table import Table from rich.table import Table
from .. import events from .. import events
from ..css.styles import Styles
from ..reactive import watch, Reactive from ..reactive import watch, Reactive
from ..widget import Widget from ..widget import Widget
@@ -49,7 +50,7 @@ class Header(Widget):
def get_clock(self) -> str: def get_clock(self) -> str:
return datetime.now().time().strftime("%X") return datetime.now().time().strftime("%X")
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
header_table = Table.grid(padding=(0, 1), expand=True) header_table = Table.grid(padding=(0, 1), expand=True)
header_table.style = self.style header_table.style = self.style
header_table.add_column(justify="left", ratio=0, width=8) header_table.add_column(justify="left", ratio=0, width=8)

View File

@@ -10,6 +10,7 @@ import rich.repr
from .. import log from .. import log
from .. import events from .. import events
from ..css.styles import Styles
from ..reactive import Reactive from ..reactive import Reactive
from ..widget import Widget from ..widget import Widget
@@ -26,7 +27,7 @@ class Placeholder(Widget, can_focus=True):
yield "has_focus", self.has_focus, False yield "has_focus", self.has_focus, False
yield "mouse_over", self.mouse_over, False yield "mouse_over", self.mouse_over, False
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return Panel( return Panel(
Align.center( Align.center(
Pretty(self, no_wrap=True, overflow="ellipsis"), vertical="middle" Pretty(self, no_wrap=True, overflow="ellipsis"), vertical="middle"

View File

@@ -4,6 +4,8 @@ from rich.console import RenderableType
from rich.padding import Padding, PaddingDimensions from rich.padding import Padding, PaddingDimensions
from rich.style import StyleType from rich.style import StyleType
from rich.styled import Styled from rich.styled import Styled
from ..css.styles import Styles
from ..widget import Widget from ..widget import Widget
@@ -23,7 +25,7 @@ class Static(Widget):
self.style = style self.style = style
self.padding = padding self.padding = padding
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
renderable = self.renderable renderable = self.renderable
if self.padding: if self.padding:
renderable = Padding(renderable, self.padding) renderable = Padding(renderable, self.padding)

View File

@@ -249,7 +249,7 @@ class TreeControl(Generic[NodeDataType], Widget):
push(iter(node.children)) push(iter(node.children))
return None return None
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return self._tree return self._tree
def render_node(self, node: TreeNode[NodeDataType]) -> RenderableType: def render_node(self, node: TreeNode[NodeDataType]) -> RenderableType:

View File

@@ -330,7 +330,7 @@ class Tabs(Widget):
""" """
return next((i for i, tab in enumerate(self.tabs) if tab.name == tab_name), 0) return next((i for i, tab in enumerate(self.tabs) if tab.name == tab_name), 0)
def render(self) -> RenderableType: def render(self, styles: Styles) -> RenderableType:
return TabsRenderable( return TabsRenderable(
self.tabs, self.tabs,
tab_padding=self.tab_padding, tab_padding=self.tab_padding,

View File

@@ -1,10 +1,8 @@
from contextlib import nullcontext as does_not_raise
from decimal import Decimal
import pytest import pytest
from textual.app import App from textual.app import App
from textual.css.errors import StyleValueError from textual.css.errors import StyleValueError
from textual.css.styles import Styles
from textual.geometry import Size from textual.geometry import Size
from textual.widget import Widget from textual.widget import Widget
@@ -41,7 +39,7 @@ def test_widget_content_width():
self.text = text self.text = text
super().__init__(id=id) super().__init__(id=id)
def render(self) -> str: def render(self, styles: Styles) -> str:
return self.text return self.text
widget1 = TextWidget("foo", id="widget1") widget1 = TextWidget("foo", id="widget1")