mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Added watch method
This commit is contained in:
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Added Shift+scroll wheel and ctrl+scroll wheel to scroll horizontally
|
||||
- Added `Tree.action_toggle_node` to toggle a node without selecting, and bound it to <kbd>Space</kbd> https://github.com/Textualize/textual/issues/1433
|
||||
- Added `Tree.reset` to fully reset a `Tree` https://github.com/Textualize/textual/issues/1437
|
||||
- Added DOMNode.watch method https://github.com/Textualize/textual/pull/1750
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ from rich.text import Text
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.binding import Binding
|
||||
from textual.containers import Container, Horizontal
|
||||
from textual.reactive import reactive, watch
|
||||
from textual.reactive import reactive
|
||||
from textual.widgets import (
|
||||
Button,
|
||||
Checkbox,
|
||||
@@ -203,7 +203,7 @@ class DarkSwitch(Horizontal):
|
||||
yield Static("Dark mode toggle", classes="label")
|
||||
|
||||
def on_mount(self) -> None:
|
||||
watch(self.app, "dark", self.on_dark_change, init=False)
|
||||
self.watch(self.app, "dark", self.on_dark_change, init=False)
|
||||
|
||||
def on_dark_change(self, dark: bool) -> None:
|
||||
self.query_one(Checkbox).value = self.app.dark
|
||||
|
||||
@@ -4,6 +4,7 @@ import re
|
||||
from inspect import getfile
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Callable,
|
||||
ClassVar,
|
||||
Iterable,
|
||||
Iterator,
|
||||
@@ -31,7 +32,7 @@ from .css.parse import parse_declarations
|
||||
from .css.styles import RenderStyles, Styles
|
||||
from .css.tokenize import IDENTIFIER
|
||||
from .message_pump import MessagePump
|
||||
from .reactive import Reactive
|
||||
from .reactive import Reactive, _watch
|
||||
from .timer import Timer
|
||||
from .walk import walk_breadth_first, walk_depth_first
|
||||
|
||||
@@ -647,6 +648,19 @@ class DOMNode(MessagePump):
|
||||
"""
|
||||
return [child for child in self.children if child.display]
|
||||
|
||||
def watch(
|
||||
self, obj: DOMNode, attribute_name: str, callback: Callable, init: bool = True
|
||||
) -> None:
|
||||
"""Watches for modifications to reactive attributes on another object.
|
||||
|
||||
Args:
|
||||
obj: Object containing attribute to watch.
|
||||
attribute_name: Attribute to watch.
|
||||
callback: A callback to run when attribute changes.
|
||||
init: Check watchers on first call.
|
||||
"""
|
||||
_watch(self, obj, attribute_name, callback, init=init)
|
||||
|
||||
def get_pseudo_classes(self) -> Iterable[str]:
|
||||
"""Get any pseudo classes applicable to this Node, e.g. hover, focus.
|
||||
|
||||
|
||||
@@ -126,7 +126,6 @@ class MessagePump(metaclass=MessagePumpMeta):
|
||||
@property
|
||||
def is_attached(self) -> bool:
|
||||
"""Check the node is attached to the app via the DOM."""
|
||||
|
||||
from .app import App
|
||||
|
||||
node = self
|
||||
|
||||
@@ -325,10 +325,12 @@ class var(Reactive[ReactiveType]):
|
||||
)
|
||||
|
||||
|
||||
def watch(
|
||||
def _watch(
|
||||
node: DOMNode,
|
||||
obj: Reactable,
|
||||
attribute_name: str,
|
||||
callback: Callable[[Any], object],
|
||||
*,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Watch a reactive variable on an object.
|
||||
@@ -346,7 +348,7 @@ def watch(
|
||||
watcher_list = watchers.setdefault(attribute_name, [])
|
||||
if callback in watcher_list:
|
||||
return
|
||||
watcher_list.append((obj, callback))
|
||||
watcher_list.append((node, callback))
|
||||
if init:
|
||||
current_value = getattr(obj, attribute_name, None)
|
||||
Reactive._check_watchers(obj, attribute_name, current_value)
|
||||
|
||||
@@ -8,7 +8,7 @@ from rich.console import RenderableType
|
||||
from rich.text import Text
|
||||
|
||||
from .. import events
|
||||
from ..reactive import Reactive, watch
|
||||
from ..reactive import Reactive
|
||||
from ..widget import Widget
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class Footer(Widget):
|
||||
self.refresh()
|
||||
|
||||
def on_mount(self) -> None:
|
||||
watch(self.screen, "focused", self._focus_changed)
|
||||
self.watch(self.screen, "focused", self._focus_changed)
|
||||
|
||||
def _focus_changed(self, focused: Widget | None) -> None:
|
||||
self._key_text = None
|
||||
|
||||
@@ -5,7 +5,7 @@ from datetime import datetime
|
||||
from rich.text import Text
|
||||
|
||||
from ..widget import Widget
|
||||
from ..reactive import Reactive, watch
|
||||
from ..reactive import Reactive
|
||||
|
||||
|
||||
class HeaderIcon(Widget):
|
||||
@@ -133,5 +133,5 @@ class Header(Widget):
|
||||
def set_sub_title(sub_title: str) -> None:
|
||||
self.query_one(HeaderTitle).sub_text = sub_title
|
||||
|
||||
watch(self.app, "title", set_title)
|
||||
watch(self.app, "sub_title", set_sub_title)
|
||||
self.watch(self.app, "title", set_title)
|
||||
self.watch(self.app, "sub_title", set_sub_title)
|
||||
|
||||
Reference in New Issue
Block a user