Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 33 additions & 46 deletions src/textual/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,8 +455,6 @@ def __init__(
self._layout_cache: dict[str, object] = {}
"""A dict that is refreshed when the widget is resized / refreshed."""

self._visual_style: VisualStyle | None = None

self._render_cache = _RenderCache(_null_size, [])
# Regions which need to be updated (in Widget)
self._dirty_regions: set[Region] = set()
Expand Down Expand Up @@ -721,14 +719,6 @@ def preflight_checks(self) -> None:
f"'{self.__class__.__name__}.CSS' will be ignored (use 'DEFAULT_CSS' class variable for widgets)"
)

def pre_render(self) -> None:
"""Called prior to rendering.

If you implement this in a subclass, be sure to call the base class method via super.

"""
self._visual_style = None

def _cover(self, widget: Widget) -> None:
"""Set a widget used to replace the visuals of this widget (used for loading indicator).

Expand Down Expand Up @@ -4127,43 +4117,41 @@ def _scroll_update(self, virtual_size: Size) -> None:

@property
def visual_style(self) -> VisualStyle:
if self._visual_style is None:
background = Color(0, 0, 0, 0)
color = Color(255, 255, 255, 0)

style = Style()
opacity = 1.0
background = Color(0, 0, 0, 0)
color = Color(255, 255, 255, 0)

for node in reversed(self.ancestors_with_self):
styles = node.styles
has_rule = styles.has_rule
opacity *= styles.opacity
if has_rule("background"):
text_background = background + styles.background.tint(
styles.background_tint
)
background += (
styles.background.tint(styles.background_tint)
).multiply_alpha(opacity)
else:
text_background = background
if has_rule("color"):
color = styles.color
style += styles.text_style
if has_rule("auto_color") and styles.auto_color:
color = text_background.get_contrast_text(color.a)
style = Style()
opacity = 1.0

self._visual_style = VisualStyle(
background,
color,
bold=style.bold,
dim=style.dim,
italic=style.italic,
reverse=style.reverse,
underline=style.underline,
strike=style.strike,
)
return self._visual_style
for node in reversed(self.ancestors_with_self):
styles = node.styles
has_rule = styles.has_rule
opacity *= styles.opacity
if has_rule("background"):
text_background = background + styles.background.tint(
styles.background_tint
)
background += (
styles.background.tint(styles.background_tint)
).multiply_alpha(opacity)
else:
text_background = background
if has_rule("color"):
color = styles.color
style += styles.text_style
if has_rule("auto_color") and styles.auto_color:
color = text_background.get_contrast_text(color.a)

return VisualStyle(
background,
color,
bold=style.bold,
dim=style.dim,
italic=style.italic,
reverse=style.reverse,
underline=style.underline,
strike=style.strike,
)

def get_selection(self, selection: Selection) -> tuple[str, str] | None:
"""Get the text under the selection.
Expand Down Expand Up @@ -4633,7 +4621,6 @@ async def broker_event(self, event_name: str, event: events.Event) -> bool:
def notify_style_update(self) -> None:
self._rich_style_cache.clear()
self._visual_style_cache.clear()
self._visual_style = None
super().notify_style_update()

async def _on_mouse_down(self, event: events.MouseDown) -> None:
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions tests/snapshot_tests/test_snapshots.py
Original file line number Diff line number Diff line change
Expand Up @@ -4804,3 +4804,28 @@ async def run_before(pilot: Pilot) -> None:
await pilot.press("ctrl+v")

assert snap_compare(TextAreaApp(), run_before=run_before)


def test_visual_updates_after_style_changes(snap_compare) -> None:
"""Regression test for https://github.com/Textualize/textual/issues/6289

You should see a widget with a red background and yellow text.
"""

class UpdateStylesApp(App):
CSS = """
Static {
height: 1fr;
content-align: center middle;
}
"""

def compose(self) -> ComposeResult:
yield Static("yellow on red")

def key_s(self) -> None:
widget = self.query_one(Static)
widget.styles.color = "yellow"
widget.styles.background = "red"

assert snap_compare(UpdateStylesApp(), press=["s"])
Loading