mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
fix for focus reset edge case
This commit is contained in:
@@ -196,6 +196,7 @@ DataTable {
|
||||
height: 16;
|
||||
}
|
||||
|
||||
|
||||
LoginForm {
|
||||
height: auto;
|
||||
margin: 1 0;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from rich import box
|
||||
from rich.console import RenderableType
|
||||
from rich.markdown import Markdown
|
||||
@@ -303,6 +305,7 @@ class DemoApp(App):
|
||||
self.query_one(TextLog).write(renderable)
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
example_css = "\n".join(Path(self.css_path).read_text().splitlines()[:50])
|
||||
yield Container(
|
||||
Sidebar(classes="-hidden"),
|
||||
Header(show_clock=True),
|
||||
@@ -341,9 +344,15 @@ class DemoApp(App):
|
||||
Section(
|
||||
SectionTitle("CSS"),
|
||||
Text(Markdown(CSS_MD)),
|
||||
Static(
|
||||
Syntax(
|
||||
EXAMPLE_CSS, "css", theme="material", line_numbers=True
|
||||
Window(
|
||||
Static(
|
||||
Syntax(
|
||||
example_css,
|
||||
"css",
|
||||
theme="material",
|
||||
line_numbers=True,
|
||||
),
|
||||
expand=True,
|
||||
)
|
||||
),
|
||||
),
|
||||
|
||||
@@ -278,7 +278,7 @@ class DOMNode(MessagePump):
|
||||
while node and not isinstance(node, Screen):
|
||||
node = node._parent
|
||||
if not isinstance(node, Screen):
|
||||
raise NoScreen(f"{self} has no screen")
|
||||
raise NoScreen(f"node has no screen")
|
||||
return node
|
||||
|
||||
@property
|
||||
|
||||
@@ -225,7 +225,7 @@ class Screen(Widget):
|
||||
return self._move_focus(-1)
|
||||
|
||||
def _reset_focus(
|
||||
self, widget: Widget, avoiding: list[DOMNode] | None = None
|
||||
self, widget: Widget, avoiding: list[Widget] | None = None
|
||||
) -> None:
|
||||
"""Reset the focus when a widget is removed
|
||||
|
||||
@@ -252,14 +252,20 @@ class Screen(Widget):
|
||||
# the focus chain.
|
||||
widget_index = focusable_widgets.index(widget)
|
||||
except ValueError:
|
||||
# Seems we can't find it. There's no good reason this should
|
||||
# happen but, on the off-chance, let's go into a "no focus" state.
|
||||
self.set_focus(None)
|
||||
# widget is not in focusable widgets
|
||||
# It may have been made invisible
|
||||
# Move to a sibling if possible
|
||||
for sibling in widget.visible_siblings:
|
||||
if sibling not in avoiding and sibling.can_focus:
|
||||
self.set_focus(sibling)
|
||||
break
|
||||
else:
|
||||
self.set_focus(None)
|
||||
return
|
||||
|
||||
# Now go looking for something before it, that isn't about to be
|
||||
# removed, and which can receive focus, and go focus that.
|
||||
chosen: DOMNode | None = None
|
||||
chosen: Widget | None = None
|
||||
for candidate in reversed(
|
||||
focusable_widgets[widget_index + 1 :] + focusable_widgets[:widget_index]
|
||||
):
|
||||
@@ -368,6 +374,7 @@ class Screen(Widget):
|
||||
hidden, shown, resized = self._compositor.reflow(self, size)
|
||||
Hide = events.Hide
|
||||
Show = events.Show
|
||||
|
||||
for widget in hidden:
|
||||
widget.post_message_no_wait(Hide(self))
|
||||
for widget in shown:
|
||||
|
||||
@@ -261,6 +261,18 @@ class Widget(DOMNode):
|
||||
else:
|
||||
return []
|
||||
|
||||
@property
|
||||
def visible_siblings(self) -> list[Widget]:
|
||||
"""A list of siblings which will be shown.
|
||||
|
||||
Returns:
|
||||
list[Widget]: List of siblings.
|
||||
"""
|
||||
siblings = [
|
||||
widget for widget in self.siblings if widget.visible and widget.display
|
||||
]
|
||||
return siblings
|
||||
|
||||
@property
|
||||
def allow_vertical_scroll(self) -> bool:
|
||||
"""Check if vertical scroll is permitted.
|
||||
@@ -1576,9 +1588,12 @@ class Widget(DOMNode):
|
||||
yield "hover"
|
||||
if self.has_focus:
|
||||
yield "focus"
|
||||
focused = self.screen.focused
|
||||
if focused and self in focused.ancestors:
|
||||
yield "focus-within"
|
||||
try:
|
||||
focused = self.screen.focused
|
||||
if focused and self in focused.ancestors:
|
||||
yield "focus-within"
|
||||
except NoScreen:
|
||||
pass
|
||||
|
||||
def post_render(self, renderable: RenderableType) -> ConsoleRenderable:
|
||||
"""Applies style attributes to the default renderable.
|
||||
|
||||
Reference in New Issue
Block a user