Merge pull request #2325 from davep/private-event-handlers

Make textual.widgets.* event handlers private
This commit is contained in:
Dave Pearson
2023-04-19 11:15:29 +01:00
committed by GitHub
15 changed files with 54 additions and 43 deletions

View File

@@ -5,6 +5,7 @@ from __future__ import annotations
from typing import Optional from typing import Optional
from ..containers import Container from ..containers import Container
from ..events import Mount
from ..reactive import reactive from ..reactive import reactive
from ..widget import Widget from ..widget import Widget
@@ -58,7 +59,7 @@ class ContentSwitcher(Container):
) )
self._initial = initial self._initial = initial
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
"""Perform the initial setup of the widget once the DOM is ready.""" """Perform the initial setup of the widget once the DOM is ready."""
initial = self._initial initial = self._initial
with self.app.batch_update(): with self.app.batch_update():

View File

@@ -887,11 +887,11 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
return self.header_height return self.header_height
return self.rows[row_key].height return self.rows[row_key].height
async def on_styles_updated(self) -> None: async def _on_styles_updated(self) -> None:
self._clear_caches() self._clear_caches()
self.refresh() self.refresh()
def on_resize(self, event: events.Resize) -> None: def _on_resize(self, _: events.Resize) -> None:
self._update_count += 1 self._update_count += 1
def watch_show_cursor(self, show_cursor: bool) -> None: def watch_show_cursor(self, show_cursor: bool) -> None:
@@ -1364,7 +1364,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
self._update_count += 1 self._update_count += 1
self.refresh(layout=True) self.refresh(layout=True)
def on_idle(self) -> None: async def _on_idle(self, _: events.Idle) -> None:
"""Runs when the message pump is empty. """Runs when the message pump is empty.
We use this for some expensive calculations like re-computing dimensions of the We use this for some expensive calculations like re-computing dimensions of the
@@ -1904,7 +1904,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
return self._render_line(y, scroll_x, scroll_x + width, self.rich_style) return self._render_line(y, scroll_x, scroll_x + width, self.rich_style)
def on_mouse_move(self, event: events.MouseMove): def _on_mouse_move(self, event: events.MouseMove):
"""If the hover cursor is visible, display it by extracting the row """If the hover cursor is visible, display it by extracting the row
and column metadata from the segments present in the cells.""" and column metadata from the segments present in the cells."""
self._set_hover_cursor(True) self._set_hover_cursor(True)
@@ -1916,7 +1916,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
except KeyError: except KeyError:
pass pass
def on_leave(self, event: events.Leave) -> None: def _on_leave(self, _: events.Leave) -> None:
self._set_hover_cursor(False) self._set_hover_cursor(False)
def _get_fixed_offset(self) -> Spacing: def _get_fixed_offset(self) -> Spacing:
@@ -2001,7 +2001,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
elif cursor_type == "cell": elif cursor_type == "cell":
self.refresh_coordinate(self.hover_coordinate) self.refresh_coordinate(self.hover_coordinate)
def on_click(self, event: events.Click) -> None: async def _on_click(self, event: events.Click) -> None:
self._set_hover_cursor(True) self._set_hover_cursor(True)
meta = event.style.meta meta = event.style.meta
if not meta: if not meta:

View File

@@ -8,6 +8,7 @@ from typing import ClassVar, Iterable
from rich.style import Style from rich.style import Style
from rich.text import Text, TextType from rich.text import Text, TextType
from ..events import Mount
from ..message import Message from ..message import Message
from ._tree import TOGGLE_STYLE, Tree, TreeNode from ._tree import TOGGLE_STYLE, Tree, TreeNode
@@ -180,10 +181,10 @@ class DirectoryTree(Tree[DirEntry]):
) )
node.expand() node.expand()
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
self.load_directory(self.root) self.load_directory(self.root)
def on_tree_node_expanded(self, event: Tree.NodeSelected) -> None: def _on_tree_node_expanded(self, event: Tree.NodeSelected) -> None:
event.stop() event.stop()
dir_entry = event.node.data dir_entry = event.node.data
if dir_entry is None: if dir_entry is None:
@@ -194,7 +195,7 @@ class DirectoryTree(Tree[DirEntry]):
else: else:
self.post_message(self.FileSelected(dir_entry.path)) self.post_message(self.FileSelected(dir_entry.path))
def on_tree_node_selected(self, event: Tree.NodeSelected) -> None: def _on_tree_node_selected(self, event: Tree.NodeSelected) -> None:
event.stop() event.stop()
dir_entry = event.node.data dir_entry = event.node.data
if dir_entry is None: if dir_entry is None:

View File

@@ -7,6 +7,7 @@ from datetime import datetime
from rich.text import Text from rich.text import Text
from ..app import RenderResult from ..app import RenderResult
from ..events import Mount
from ..reactive import Reactive from ..reactive import Reactive
from ..widget import Widget from ..widget import Widget
@@ -67,7 +68,7 @@ class HeaderClock(HeaderClockSpace):
} }
""" """
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
self.set_interval(1, callback=self.refresh, name=f"update header clock") self.set_interval(1, callback=self.refresh, name=f"update header clock")
def render(self) -> RenderResult: def render(self) -> RenderResult:
@@ -156,10 +157,10 @@ class Header(Widget):
def watch_tall(self, tall: bool) -> None: def watch_tall(self, tall: bool) -> None:
self.set_class(tall, "-tall") self.set_class(tall, "-tall")
def on_click(self): def _on_click(self):
self.toggle_class("-tall") self.toggle_class("-tall")
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
def set_title(title: str) -> None: def set_title(title: str) -> None:
self.query_one(HeaderTitle).text = title self.query_one(HeaderTitle).text = title

View File

@@ -12,6 +12,7 @@ from rich.text import Text
from .. import events from .. import events
from .._segment_tools import line_crop from .._segment_tools import line_crop
from ..binding import Binding, BindingType from ..binding import Binding, BindingType
from ..events import Blur, Focus, Mount
from ..geometry import Size from ..geometry import Size
from ..message import Message from ..message import Message
from ..reactive import reactive from ..reactive import reactive
@@ -299,22 +300,22 @@ class Input(Widget, can_focus=True):
"""Toggle visibility of cursor.""" """Toggle visibility of cursor."""
self._cursor_visible = not self._cursor_visible self._cursor_visible = not self._cursor_visible
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
self.blink_timer = self.set_interval( self.blink_timer = self.set_interval(
0.5, 0.5,
self._toggle_cursor, self._toggle_cursor,
pause=not (self.cursor_blink and self.has_focus), pause=not (self.cursor_blink and self.has_focus),
) )
def on_blur(self) -> None: def _on_blur(self, _: Blur) -> None:
self.blink_timer.pause() self.blink_timer.pause()
def on_focus(self) -> None: def _on_focus(self, _: Focus) -> None:
self.cursor_position = len(self.value) self.cursor_position = len(self.value)
if self.cursor_blink: if self.cursor_blink:
self.blink_timer.resume() self.blink_timer.resume()
async def on_key(self, event: events.Key) -> None: async def _on_key(self, event: events.Key) -> None:
self._cursor_visible = True self._cursor_visible = True
if self.cursor_blink: if self.cursor_blink:
self.blink_timer.reset() self.blink_timer.reset()
@@ -330,12 +331,12 @@ class Input(Widget, can_focus=True):
self.insert_text_at_cursor(event.character) self.insert_text_at_cursor(event.character)
event.prevent_default() event.prevent_default()
def on_paste(self, event: events.Paste) -> None: def _on_paste(self, event: events.Paste) -> None:
line = event.text.splitlines()[0] line = event.text.splitlines()[0]
self.insert_text_at_cursor(line) self.insert_text_at_cursor(line)
event.stop() event.stop()
def on_click(self, event: events.Click) -> None: async def _on_click(self, event: events.Click) -> None:
offset = event.get_content_offset(self) offset = event.get_content_offset(self)
if offset is None: if offset is None:
return return

View File

@@ -47,7 +47,7 @@ class ListItem(Widget, can_focus=False):
self.item = item self.item = item
super().__init__() super().__init__()
def on_click(self, event: events.Click) -> None: async def _on_click(self, _: events.Click) -> None:
self.post_message(self._ChildClicked(self)) self.post_message(self._ChildClicked(self))
def watch_highlighted(self, value: bool) -> None: def watch_highlighted(self, value: bool) -> None:

View File

@@ -5,6 +5,7 @@ from typing import ClassVar, Optional
from textual.await_remove import AwaitRemove from textual.await_remove import AwaitRemove
from textual.binding import Binding, BindingType from textual.binding import Binding, BindingType
from textual.containers import VerticalScroll from textual.containers import VerticalScroll
from textual.events import Mount
from textual.geometry import clamp from textual.geometry import clamp
from textual.message import Message from textual.message import Message
from textual.reactive import reactive from textual.reactive import reactive
@@ -93,7 +94,7 @@ class ListView(VerticalScroll, can_focus=True, can_focus_children=False):
) )
self._index = initial_index self._index = initial_index
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
"""Ensure the ListView is fully-settled after mounting.""" """Ensure the ListView is fully-settled after mounting."""
self.index = self._index self.index = self._index
@@ -196,7 +197,7 @@ class ListView(VerticalScroll, can_focus=True, can_focus_children=False):
return return
self.index -= 1 self.index -= 1
def on_list_item__child_clicked(self, event: ListItem._ChildClicked) -> None: def _on_list_item__child_clicked(self, event: ListItem._ChildClicked) -> None:
self.focus() self.focus()
self.index = self._nodes.index(event.item) self.index = self._nodes.index(event.item)
self.post_message(self.Selected(self, event.item)) self.post_message(self.Selected(self, event.item))

View File

@@ -7,6 +7,7 @@ from rich.style import Style
from rich.text import Text from rich.text import Text
from ..color import Gradient from ..color import Gradient
from ..events import Mount
from ..widget import Widget from ..widget import Widget
@@ -22,7 +23,7 @@ class LoadingIndicator(Widget):
} }
""" """
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
self._start_time = time() self._start_time = time()
self.auto_refresh = 1 / 16 self.auto_refresh = 1 / 16

View File

@@ -13,6 +13,7 @@ from typing_extensions import TypeAlias
from ..app import ComposeResult from ..app import ComposeResult
from ..containers import Horizontal, VerticalScroll from ..containers import Horizontal, VerticalScroll
from ..events import Mount
from ..message import Message from ..message import Message
from ..reactive import reactive, var from ..reactive import reactive, var
from ..widget import Widget from ..widget import Widget
@@ -587,7 +588,7 @@ class Markdown(Widget):
self.href: str = href self.href: str = href
"""The link that was selected.""" """The link that was selected."""
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
if self._markdown is not None: if self._markdown is not None:
self.update(self._markdown) self.update(self._markdown)
@@ -801,7 +802,7 @@ class MarkdownTableOfContents(Widget, can_focus_children=True):
node = node.add(NUMERALS[level], expand=True) node = node.add(NUMERALS[level], expand=True)
node.add_leaf(f"[dim]{NUMERALS[level]}[/] {name}", {"block_id": block_id}) node.add_leaf(f"[dim]{NUMERALS[level]}[/] {name}", {"block_id": block_id})
async def on_tree_node_selected(self, message: Tree.NodeSelected) -> None: async def _on_tree_node_selected(self, message: Tree.NodeSelected) -> None:
node_data = message.node.data node_data = message.node.data
if node_data is not None: if node_data is not None:
await self._post_message( await self._post_message(
@@ -872,7 +873,7 @@ class MarkdownViewer(VerticalScroll, can_focus=True, can_focus_children=True):
"""The table of contents widget""" """The table of contents widget"""
return self.query_one(MarkdownTableOfContents) return self.query_one(MarkdownTableOfContents)
async def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
if self._markdown is not None: if self._markdown is not None:
self.document.update(self._markdown) self.document.update(self._markdown)
@@ -890,7 +891,7 @@ class MarkdownViewer(VerticalScroll, can_focus=True, can_focus_children=True):
if self.navigator.forward(): if self.navigator.forward():
await self.document.load(self.navigator.location) await self.document.load(self.navigator.location)
async def on_markdown_link_clicked(self, message: Markdown.LinkClicked) -> None: async def _on_markdown_link_clicked(self, message: Markdown.LinkClicked) -> None:
message.stop() message.stop()
await self.go(message.href) await self.go(message.href)
@@ -901,7 +902,7 @@ class MarkdownViewer(VerticalScroll, can_focus=True, can_focus_children=True):
yield MarkdownTableOfContents() yield MarkdownTableOfContents()
yield Markdown(parser_factory=self._parser_factory) yield Markdown(parser_factory=self._parser_factory)
def on_markdown_table_of_contents_updated( def _on_markdown_table_of_contents_updated(
self, message: Markdown.TableOfContentsUpdated self, message: Markdown.TableOfContentsUpdated
) -> None: ) -> None:
self.query_one( self.query_one(
@@ -909,7 +910,7 @@ class MarkdownViewer(VerticalScroll, can_focus=True, can_focus_children=True):
).table_of_contents = message.table_of_contents ).table_of_contents = message.table_of_contents
message.stop() message.stop()
def on_markdown_table_of_contents_selected( def _on_markdown_table_of_contents_selected(
self, message: Markdown.TableOfContentsSelected self, message: Markdown.TableOfContentsSelected
) -> None: ) -> None:
block_selector = f"#{message.block_id}" block_selector = f"#{message.block_id}"

View File

@@ -16,7 +16,7 @@ from rich.style import Style
from typing_extensions import Literal, Self, TypeAlias from typing_extensions import Literal, Self, TypeAlias
from ..binding import Binding, BindingType from ..binding import Binding, BindingType
from ..events import Click, MouseMove from ..events import Click, Idle, Leave, MouseMove
from ..geometry import Region, Size from ..geometry import Region, Size
from ..message import Message from ..message import Message
from ..reactive import reactive from ..reactive import reactive
@@ -363,7 +363,7 @@ class OptionList(ScrollView, can_focus=True):
self._needs_to_scroll_to_highlight = rescroll_to_highlight self._needs_to_scroll_to_highlight = rescroll_to_highlight
self.check_idle() self.check_idle()
def on_idle(self) -> None: async def _on_idle(self, _: Idle) -> None:
"""Perform content tracking data refresh when idle.""" """Perform content tracking data refresh when idle."""
self._refresh_content_tracking() self._refresh_content_tracking()
if self._needs_to_scroll_to_highlight: if self._needs_to_scroll_to_highlight:
@@ -380,11 +380,11 @@ class OptionList(ScrollView, can_focus=True):
""" """
self._request_content_tracking_refresh() self._request_content_tracking_refresh()
def on_resize(self) -> None: def _on_resize(self) -> None:
"""Refresh the layout of the renderables in the list when resized.""" """Refresh the layout of the renderables in the list when resized."""
self._request_content_tracking_refresh(rescroll_to_highlight=True) self._request_content_tracking_refresh(rescroll_to_highlight=True)
def on_mouse_move(self, event: MouseMove) -> None: def _on_mouse_move(self, event: MouseMove) -> None:
"""React to the mouse moving. """React to the mouse moving.
Args: Args:
@@ -392,11 +392,11 @@ class OptionList(ScrollView, can_focus=True):
""" """
self._mouse_hovering_over = event.style.meta.get("option") self._mouse_hovering_over = event.style.meta.get("option")
def on_leave(self) -> None: def _on_leave(self, _: Leave) -> None:
"""React to the mouse leaving the widget.""" """React to the mouse leaving the widget."""
self._mouse_hovering_over = None self._mouse_hovering_over = None
def on_click(self, event: Click) -> None: async def _on_click(self, event: Click) -> None:
"""React to the mouse being clicked on an item. """React to the mouse being clicked on an item.
Args: Args:

View File

@@ -156,11 +156,11 @@ class Placeholder(Widget):
) )
return variant return variant
def on_click(self) -> None: async def _on_click(self, _: events.Click) -> None:
"""Click handler to cycle through the placeholder variants.""" """Click handler to cycle through the placeholder variants."""
self.cycle_variant() self.cycle_variant()
def on_resize(self, event: events.Resize) -> None: def _on_resize(self, event: events.Resize) -> None:
"""Update the placeholder "size" variant with the new placeholder size.""" """Update the placeholder "size" variant with the new placeholder size."""
self._renderables["size"] = self._SIZE_RENDER_TEMPLATE.format(*event.size) self._renderables["size"] = self._SIZE_RENDER_TEMPLATE.format(*event.size)
if self.variant == "size": if self.variant == "size":

View File

@@ -5,6 +5,7 @@ from __future__ import annotations
import rich.repr import rich.repr
from ..containers import Container from ..containers import Container
from ..events import Mount
from ..message import Message from ..message import Message
from ._radio_button import RadioButton from ._radio_button import RadioButton
@@ -91,7 +92,7 @@ class RadioSet(Container):
disabled=disabled, disabled=disabled,
) )
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
"""Perform some processing once mounted in the DOM.""" """Perform some processing once mounted in the DOM."""
# It's possible for the user to pass in a collection of radio # It's possible for the user to pass in a collection of radio
@@ -108,7 +109,7 @@ class RadioSet(Container):
if switched_on: if switched_on:
self._pressed_button = switched_on[0] self._pressed_button = switched_on[0]
def on_radio_button_changed(self, event: RadioButton.Changed) -> None: def _on_radio_button_changed(self, event: RadioButton.Changed) -> None:
"""Respond to the value of a button in the set being changed. """Respond to the value of a button in the set being changed.
Args: Args:

View File

@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, ClassVar
from rich.console import RenderableType from rich.console import RenderableType
from ..binding import Binding, BindingType from ..binding import Binding, BindingType
from ..events import Click
from ..geometry import Size from ..geometry import Size
from ..message import Message from ..message import Message
from ..reactive import reactive from ..reactive import reactive
@@ -153,7 +154,7 @@ class Switch(Widget, can_focus=True):
def get_content_height(self, container: Size, viewport: Size, width: int) -> int: def get_content_height(self, container: Size, viewport: Size, width: int) -> int:
return 1 return 1
def on_click(self) -> None: async def _on_click(self, _: Click) -> None:
"""Toggle the state of the switch.""" """Toggle the state of the switch."""
self.toggle() self.toggle()

View File

@@ -11,6 +11,7 @@ from ..app import ComposeResult, RenderResult
from ..binding import Binding, BindingType from ..binding import Binding, BindingType
from ..containers import Container, Horizontal, Vertical from ..containers import Container, Horizontal, Vertical
from ..css.query import NoMatches from ..css.query import NoMatches
from ..events import Mount
from ..geometry import Offset from ..geometry import Offset
from ..message import Message from ..message import Message
from ..reactive import reactive from ..reactive import reactive
@@ -73,7 +74,7 @@ class Underline(Widget):
background_style=Style.from_color(bar_style.bgcolor), background_style=Style.from_color(bar_style.bgcolor),
) )
def on_click(self, event: events.Click): def _on_click(self, event: events.Click):
"""Catch clicks, so that the underline can activate the tabs.""" """Catch clicks, so that the underline can activate the tabs."""
event.stop() event.stop()
self.post_message(self.Clicked(event.screen_offset)) self.post_message(self.Clicked(event.screen_offset))
@@ -379,7 +380,7 @@ class Tabs(Widget, can_focus=True):
except NoMatches: except NoMatches:
return None return None
def on_mount(self) -> None: def _on_mount(self, _: Mount) -> None:
"""Make the first tab active.""" """Make the first tab active."""
if self._first_active is not None: if self._first_active is not None:
self.active = self._first_active self.active = self._first_active

View File

@@ -12,6 +12,7 @@ from rich.text import Text, TextType
from ..app import RenderResult from ..app import RenderResult
from ..binding import Binding, BindingType from ..binding import Binding, BindingType
from ..events import Click
from ..geometry import Size from ..geometry import Size
from ..message import Message from ..message import Message
from ..reactive import reactive from ..reactive import reactive
@@ -220,7 +221,7 @@ class ToggleButton(Static, can_focus=True):
""" """
self.toggle() self.toggle()
def on_click(self) -> None: async def _on_click(self, _: Click) -> None:
"""Toggle the value of the widget when clicked with the mouse.""" """Toggle the value of the widget when clicked with the mouse."""
self.toggle() self.toggle()