Skip to content

Commit

Permalink
Turn a RadioSet into a single focus switching site
Browse files Browse the repository at this point in the history
With this commit a RadioSet becomes something you can tab into and out of
with just one keypress; navigation of the buttons within moves to being done
with the cursor keys instead.

See Textualize#2368.
  • Loading branch information
davep committed Apr 25, 2023
1 parent b36afd8 commit 59506f3
Showing 1 changed file with 52 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/textual/widgets/_radio_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

from __future__ import annotations

from typing import ClassVar

import rich.repr

from ..binding import Binding, BindingType
from ..containers import Container
from ..events import Mount
from ..message import Message
Expand Down Expand Up @@ -35,6 +38,21 @@ class RadioSet(Container):
}
"""

BINDINGS: ClassVar[list[BindingType]] = [
Binding("down,right", "next_button", "", show=False),
Binding("shift+tab", "breakout_previous", "", show=False),
Binding("tab", "breakout_next", "", show=False),
Binding("up,left", "previous_button", "", show=False),
]
"""
| Key(s) | Description |
| :- | :- |
| left, up | Select the previous radio button in the set. |
| right, down | Select the next radio button in the set. |
| shift+tab | Move focus to the previous focusable widget relative to the set. |
| tab | Move focus to the next focusable widget relative to the set. |
"""

@rich.repr.auto
class Changed(Message, bubble=True):
"""Posted when the pressed button in the set changes.
Expand Down Expand Up @@ -155,3 +173,37 @@ def pressed_index(self) -> int:
if self._pressed_button is not None
else -1
)

def action_previous_button(self) -> None:
"""Navigate to the previous button in the set.
Note that this will wrap around to the end if at the start.
"""
if self.children:
if self.screen.focused == self.children[0]:
self.screen.set_focus(self.children[-1])
else:
self.screen.focus_previous()

def action_next_button(self) -> None:
"""Navigate to the next button in the set.
Note that this will wrap around to the start if at the end.
"""
if self.children:
if self.screen.focused == self.children[-1]:
self.screen.set_focus(self.children[0])
else:
self.screen.focus_next()

def action_breakout_previous(self) -> None:
"""Break out of the radio set to the previous widget in the focus chain."""
if self.children:
self.screen.set_focus(self.children[0])
self.screen.focus_previous()

def action_breakout_next(self) -> None:
"""Break out of the radio set to the next widget in the focus chain."""
if self.children:
self.screen.set_focus(self.children[-1])
self.screen.focus_next()

0 comments on commit 59506f3

Please sign in to comment.