Make auto-focus a class var.

Related comments: https://github.com/Textualize/textual/pull/2527\#discussion_r1188776849
This commit is contained in:
Rodrigo Girão Serrão
2023-05-09 16:44:37 +01:00
parent 8d3f69a04d
commit 3245eb38bb
2 changed files with 14 additions and 13 deletions

View File

@@ -9,6 +9,7 @@ from typing import (
TYPE_CHECKING,
Awaitable,
Callable,
ClassVar,
Generic,
Iterable,
Iterator,
@@ -93,6 +94,13 @@ class ResultCallback(Generic[ScreenResultType]):
class Screen(Generic[ScreenResultType], Widget):
"""The base class for screens."""
AUTO_FOCUS: ClassVar[str | None] = "*"
"""A selector to determine what to focus automatically when the screen is activated.
The widget focused is the first that matches the given [CSS selector](/guide/queries/#query-selectors).
Set to `None` to disable auto focus.
"""
DEFAULT_CSS = """
Screen {
layout: vertical;
@@ -100,13 +108,6 @@ class Screen(Generic[ScreenResultType], Widget):
background: $surface;
}
"""
auto_focus: str | None = "*"
"""A selector to determine what to focus automatically when the screen is activated.
The widget focused is the first that matches the given [CSS selector](/guide/queries/#query-selectors).
Set to `None` to disable auto focus.
"""
focused: Reactive[Widget | None] = Reactive(None)
"""The focused [widget][textual.widget.Widget] or `None` for no focus."""
stack_updates: Reactive[int] = Reactive(0, repaint=False)
@@ -665,9 +666,9 @@ class Screen(Generic[ScreenResultType], Widget):
"""Screen has resumed."""
self.stack_updates += 1
size = self.app.size
if self.auto_focus is not None and self.focused is None:
if self.AUTO_FOCUS is not None and self.focused is None:
try:
to_focus = self.query(self.auto_focus).first()
to_focus = self.query(self.AUTO_FOCUS).first()
except NoMatches:
pass
else:

View File

@@ -170,24 +170,24 @@ async def test_auto_focus():
assert isinstance(app.focused, Button)
app.pop_screen()
MyScreen.auto_focus = None
MyScreen.AUTO_FOCUS = None
await app.push_screen(MyScreen())
assert app.focused is None
app.pop_screen()
MyScreen.auto_focus = "Input"
MyScreen.AUTO_FOCUS = "Input"
await app.push_screen(MyScreen())
assert isinstance(app.focused, Input)
assert app.focused.id == "one"
app.pop_screen()
MyScreen.auto_focus = "#two"
MyScreen.AUTO_FOCUS = "#two"
await app.push_screen(MyScreen())
assert isinstance(app.focused, Input)
assert app.focused.id == "two"
# If we push and pop another screen, focus should be preserved for #two.
MyScreen.auto_focus = None
MyScreen.AUTO_FOCUS = None
await app.push_screen(MyScreen())
assert app.focused is None
app.pop_screen()