Further removal of App.dark from various places, swapping in App.theme equivalents

This commit is contained in:
Darren Burns
2024-10-24 17:11:25 +01:00
parent f8af2005ed
commit 0c5f611c44
8 changed files with 34 additions and 55 deletions

View File

@@ -327,7 +327,7 @@ The `background: green` is only applied to the Button underneath the mouse curso
Here are some other pseudo classes:
- `:blur` Matches widgets which *do not* have input focus.
- `:dark` Matches widgets in dark mode (where `App.dark == True`).
- `:dark` Matches widgets in dark themes (where `App.theme.dark == True`).
- `:disabled` Matches widgets which are in a disabled state.
- `:enabled` Matches widgets which are in an enabled state.
- `:even` Matches a widget at an evenly numbered position within its siblings.
@@ -336,7 +336,7 @@ Here are some other pseudo classes:
- `:focus` Matches widgets which have input focus.
- `:inline` Matches widgets when the app is running in inline mode.
- `:last-of-type` Matches a widget that is the last of its type amongst its siblings.
- `:light` Matches widgets in dark mode (where `App.dark == False`).
- `:light` Matches widgets in light themes (where `App.theme.dark == False`).
- `:odd` Matches a widget at an oddly numbered position within its siblings.
## Combinators

View File

@@ -248,7 +248,7 @@ class ChangingThemeApp(App[None]):
def compose(self) -> ComposeResult:
with Grid(id="palette"):
theme = self.get_theme(self.theme)
theme = self.current_theme
for variable, value in vars(theme).items():
if variable not in {
"name",

View File

@@ -90,8 +90,7 @@ class TextAreaTheme:
if self.base_style.color is None:
self.base_style = Style(color="#f3f3f3", bgcolor=self.base_style.bgcolor)
app = text_area.app
app_theme = app.get_theme(app.theme)
app_theme = text_area.app.current_theme
if self.base_style.bgcolor is None:
self.base_style = Style(

View File

@@ -558,7 +558,9 @@ class App(Generic[ReturnType], DOMNode):
This excludes the built-in themes."""
ansi_theme = self.ansi_theme_dark if self.dark else self.ansi_theme_light
ansi_theme = (
self.ansi_theme_dark if self.current_theme.dark else self.ansi_theme_light
)
self.set_reactive(App.ansi_color, ansi_color)
self._filters: list[LineFilter] = [
ANSIToTruecolor(ansi_theme, enabled=not ansi_color)
@@ -764,8 +766,8 @@ class App(Generic[ReturnType], DOMNode):
perform work after the app has resumed.
"""
self.set_class(self.dark, "-dark-mode")
self.set_class(not self.dark, "-light-mode")
self.set_class(self.current_theme.dark, "-dark-mode")
self.set_class(not self.current_theme.dark, "-light-mode")
self.animation_level: AnimationLevel = constants.TEXTUAL_ANIMATIONS
"""Determines what type of animations the app will display.
@@ -1183,11 +1185,7 @@ class App(Generic[ReturnType], DOMNode):
Returns:
A mapping of variable name to value.
"""
theme = self.get_theme(self.theme)
if theme is None:
# This should never happen thanks to the `App.theme` validator.
return {}
theme = self.current_theme
# Build the Textual color system from the theme.
# This will contain $secondary, $primary, $background, etc.
variables = theme.to_color_system().generate()
@@ -1265,28 +1263,13 @@ class App(Generic[ReturnType], DOMNode):
self.call_next(self.refresh_css)
self.call_next(self.theme_changed_signal.publish, theme)
def watch_dark(self, dark: bool) -> None:
"""Watches the dark bool.
This method handles the transition between light and dark mode when you
change the [dark][textual.app.App.dark] attribute.
"""
self.set_class(dark, "-dark-mode", update=False)
self.set_class(not dark, "-light-mode", update=False)
self._refresh_truecolor_filter(self.ansi_theme)
self.call_next(self.refresh_css)
def watch_ansi_theme_dark(self, theme: TerminalTheme) -> None:
app_theme = self.get_theme(self.theme)
assert app_theme is not None # validated by _validate_theme
if app_theme.dark:
if self.current_theme.dark:
self._refresh_truecolor_filter(theme)
self.call_next(self.refresh_css)
def watch_ansi_theme_light(self, theme: TerminalTheme) -> None:
app_theme = self.get_theme(self.theme)
assert app_theme is not None # validated by _validate_theme
if not app_theme.dark:
if not self.current_theme.dark:
self._refresh_truecolor_filter(theme)
self.call_next(self.refresh_css)
@@ -1297,9 +1280,9 @@ class App(Generic[ReturnType], DOMNode):
Defines how colors defined as ANSI (e.g. `magenta`) inside Rich renderables
are mapped to hex codes.
"""
app_theme = self.get_theme(self.theme)
assert app_theme is not None # validated by _validate_theme
return self.ansi_theme_dark if app_theme.dark else self.ansi_theme_light
return (
self.ansi_theme_dark if self.current_theme.dark else self.ansi_theme_light
)
def _refresh_truecolor_filter(self, theme: TerminalTheme) -> None:
"""Update the ANSI to Truecolor filter, if available, with a new theme mapping.

View File

@@ -237,7 +237,7 @@ class DOMNode(MessagePump):
Example:
```python
self.set_reactive(App.dark_mode, True)
self.set_reactive(App.theme, "textual-light")
```
Args:
@@ -247,15 +247,14 @@ class DOMNode(MessagePump):
Raises:
AttributeError: If the first argument is not a reactive.
"""
name = reactive.name
if not isinstance(reactive, Reactive):
raise TypeError(
"A Reactive class is required; for example: MyApp.dark_mode"
)
if reactive.name not in self._reactives:
raise TypeError("A Reactive class is required; for example: MyApp.theme")
if name not in self._reactives:
raise AttributeError(
"No reactive called {name!r}; Have you called super().__init__(...) in the {self.__class__.__name__} constructor?"
f"No reactive called {name!r}; Have you called super().__init__(...) in the {self.__class__.__name__} constructor?"
)
setattr(self, f"_reactive_{reactive.name}", value)
setattr(self, f"_reactive_{name}", value)
def mutate_reactive(self, reactive: Reactive[ReactiveType]) -> None:
"""Force an update to a mutable reactive.
@@ -1218,11 +1217,11 @@ class DOMNode(MessagePump):
Example:
```python
def on_dark_change(old_value:bool, new_value:bool) -> None:
# Called when app.dark changes.
print("App.dark went from {old_value} to {new_value}")
def on_theme_change(old_value:str, new_value:str) -> None:
# Called when app.theme changes.
print(f"App.theme went from {old_value} to {new_value}")
self.watch(self.app, "dark", self.on_dark_change, init=False)
self.watch(self.app, "theme", self.on_theme_change, init=False)
```
Args:

View File

@@ -375,8 +375,8 @@ class Widget(DOMNode):
"can-focus": lambda widget: widget.can_focus,
"disabled": lambda widget: widget.is_disabled,
"enabled": lambda widget: not widget.is_disabled,
"dark": lambda widget: widget.app.dark,
"light": lambda widget: not widget.app.dark,
"dark": lambda widget: widget.app.current_theme.dark,
"light": lambda widget: not widget.app.current_theme.dark,
"focus-within": lambda widget: widget.has_focus_within,
"inline": lambda widget: widget.app.is_inline,
"ansi": lambda widget: widget.app.ansi_color,

View File

@@ -619,10 +619,9 @@ class MarkdownFence(MarkdownBlock):
super().__init__(markdown)
self.code = code
self.lexer = lexer
app_theme = self.app.get_theme(self.app.theme)
self.theme = (
self._markdown.code_dark_theme
if app_theme.dark
if self.app.current_theme.dark
else self._markdown.code_light_theme
)
@@ -642,10 +641,9 @@ class MarkdownFence(MarkdownBlock):
def _retheme(self) -> None:
"""Rerender when the theme changes."""
app_theme = self.app.get_theme(self.app.theme)
self.theme = (
self._markdown.code_dark_theme
if app_theme.dark
if self.app.current_theme.dark
else self._markdown.code_light_theme
)
self.get_child_by_type(Static).update(self._block())
@@ -807,13 +805,13 @@ class Markdown(Widget):
def _watch_code_dark_theme(self) -> None:
"""React to the dark theme being changed."""
if self.app.dark:
if self.app.current_theme.dark:
for block in self.query(MarkdownFence):
block._retheme()
def _watch_code_light_theme(self) -> None:
"""React to the light theme being changed."""
if not self.app.dark:
if not self.app.current_theme.dark:
for block in self.query(MarkdownFence):
block._retheme()

View File

@@ -745,7 +745,7 @@ TextArea {
if padding is applied, the colors match."""
self._set_theme(theme)
def _app_dark_toggled(self) -> None:
def _app_theme_changed(self) -> None:
self._set_theme(self._theme.name)
def _set_theme(self, theme: str) -> None:
@@ -1521,8 +1521,8 @@ TextArea {
return gutter_width
def _on_mount(self, event: events.Mount) -> None:
# When `app.dark` is toggled, reset the theme (since it caches values).
self.watch(self.app, "dark", self._app_dark_toggled, init=False)
# When `app.theme` reactive is changed, reset the theme to clear cached styles.
self.watch(self.app, "theme", self._app_theme_changed, init=False)
self.blink_timer = self.set_interval(
0.5,