Improve order of focus

This commit is contained in:
Darren Burns
2022-08-05 10:13:08 +01:00
parent 5f0179ccb5
commit 5c86331c9a
4 changed files with 94 additions and 12 deletions

View File

@@ -1,6 +1,61 @@
#box { Screen {
height: 50%; height: 100vh;
width: 50%; width: 100%;
align: center middle; background: red;
}
#horizontal {
width: 100%;
}
.box {
height: 5;
width: 5;
margin: 1 10;
}
#left_pane {
width: 1fr;
background: $background;
}
#middle_pane {
margin-top: 4;
width: 1fr;
background: #173f5f;
}
#middle_pane:focus {
outline: #8bc34a;
}
#right_pane {
width: 1fr;
background: #f6d55c;
}
.box:focus {
outline: #8bc34a;
}
#box1 {
background: green; background: green;
} }
#box2 {
offset-y: 3;
background: hotpink;
}
#box3 {
background: red;
}
#box4 {
background: blue;
}
#box5 {
background: darkviolet;
}

View File

@@ -4,10 +4,11 @@ from rich.console import RenderableType
from rich.panel import Panel from rich.panel import Panel
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.layout import Horizontal, Vertical
from textual.widget import Widget from textual.widget import Widget
class Box(Widget): class Box(Widget, can_focus=True):
CSS = "#box {background: blue;}" CSS = "#box {background: blue;}"
def __init__( def __init__(
@@ -20,8 +21,25 @@ class Box(Widget):
class JustABox(App): class JustABox(App):
dark = True
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
yield Box(id="box") yield Horizontal(
Vertical(
Box(id="box1", classes="box"),
Box(id="box2", classes="box"),
Box(id="box3", classes="box"),
id="left_pane",
),
Box(id="middle_pane"),
Vertical(
Box(id="box", classes="box"),
Box(id="box4", classes="box"),
Box(id="box5", classes="box"),
id="right_pane",
),
id="horizontal",
)
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -19,15 +19,14 @@ from .css.errors import StyleValueError
from .css.parse import parse_declarations from .css.parse import parse_declarations
from .css.styles import Styles, RenderStyles from .css.styles import Styles, RenderStyles
from .css.query import NoMatchingNodesError from .css.query import NoMatchingNodesError
from .geometry import Region
from .message_pump import MessagePump from .message_pump import MessagePump
from .widget import Widget
if TYPE_CHECKING: if TYPE_CHECKING:
from .app import App from .app import App
from .css.styles import StylesBase from .css.styles import StylesBase
from .css.query import DOMQuery from .css.query import DOMQuery
from .screen import Screen from .screen import Screen
from .widget import Widget
class NoParent(Exception): class NoParent(Exception):
@@ -430,11 +429,11 @@ class DOMNode(MessagePump):
@property @property
def focusable_children(self) -> list[DOMNode]: def focusable_children(self) -> list[DOMNode]:
"""Get the children which may be focused.""" """Get the children which may be focused."""
# TODO: This may be the place to define order, other focus related rules
focusable = [ focusable = [
child for child in self.children if child.display and child.visible child for child in self.children if child.display and child.visible
] ]
return sorted(focusable, key=_focus_sort_key) sorted_focusable = sorted(focusable, key=_focus_sort_key)
return sorted_focusable
def get_pseudo_classes(self) -> Iterable[str]: def get_pseudo_classes(self) -> Iterable[str]:
"""Get any pseudo classes applicable to this Node, e.g. hover, focus. """Get any pseudo classes applicable to this Node, e.g. hover, focus.
@@ -604,5 +603,5 @@ class DOMNode(MessagePump):
def _focus_sort_key(widget: Widget) -> tuple[int, int]: def _focus_sort_key(widget: Widget) -> tuple[int, int]:
x, y = widget.content_offset x, y, _, _ = widget.region_with_margin
return y, x return y, x

View File

@@ -494,6 +494,16 @@ class Widget(DOMNode):
window_region = self.region.at_offset(self.scroll_offset) window_region = self.region.at_offset(self.scroll_offset)
return window_region return window_region
@property
def region_with_margin(self) -> Region:
"""The widget region relative to its container (*including margin*), which may not be visible,
depending on the scroll offset.
Returns:
Region: The virtual region of the Widget, inclusive of its margin.
"""
return self.virtual_region.grow(self.styles.margin)
@property @property
def scroll_offset(self) -> Offset: def scroll_offset(self) -> Offset:
return Offset(int(self.scroll_x), int(self.scroll_y)) return Offset(int(self.scroll_x), int(self.scroll_y))
@@ -736,7 +746,7 @@ class Widget(DOMNode):
""" """
# Grow the region by the margin so to keep the margin in view. # Grow the region by the margin so to keep the margin in view.
region = widget.virtual_region.grow(widget.styles.margin) region = widget.region_with_margin
scrolled = False scrolled = False
while isinstance(widget.parent, Widget) and widget is not self: while isinstance(widget.parent, Widget) and widget is not self: