Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change emit to post to self. #1738

Merged
merged 4 commits into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fixed issue with app not processing Paste event https://github.com/Textualize/textual/issues/1666
- Fixed glitch with view position with auto width inputs https://github.com/Textualize/textual/issues/1693

### Removed

- Methods `MessagePump.emit` and `MessagePump.emit_no_wait` https://github.com/Textualize/textual/pull/1738

## [0.10.1] - 2023-01-20

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ So, thanks to this bit of code in my `Activity` widget...
parent.move_child(
self, before=parent.children.index( self ) - 1
)
self.emit_no_wait( self.Moved( self ) )
self.post_message_no_wait( self.Moved( self ) )
self.scroll_visible( top=True )
```

Expand Down
4 changes: 2 additions & 2 deletions docs/examples/events/custom01.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ def on_mount(self) -> None:
self.styles.border = ("tall", self.color)

async def on_click(self) -> None:
# The emit method sends an event to a widget's parent
await self.emit(self.Selected(self, self.color))
# The post_message method sends an event to be handled in the DOM
await self.post_message(self.Selected(self, self.color))

def render(self) -> str:
return str(self.color)
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ The message class is defined within the widget class itself. This is not strictl

## Sending events

In the previous example we used [emit()][textual.message_pump.MessagePump.emit] to send an event to its parent. We could also have used [emit_no_wait()][textual.message_pump.MessagePump.emit_no_wait] for non async code. Sending messages in this way allows you to write custom widgets without needing to know in what context they will be used.
In the previous example we used [post_message()][textual.message_pump.MessagePump.post_message] to send an event to its parent. We could also have used [post_message_no_wait()][textual.message_pump.MessagePump.post_message_no_wait] for non async code. Sending messages in this way allows you to write custom widgets without needing to know in what context they will be used.

There are other ways of sending (posting) messages, which you may need to use less frequently.

Expand Down
28 changes: 0 additions & 28 deletions src/textual/message_pump.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,34 +580,6 @@ def _post_message_from_child_no_wait(self, message: Message) -> bool:
async def on_callback(self, event: events.Callback) -> None:
await invoke(event.callback)

def emit_no_wait(self, message: Message) -> bool:
"""Send a message to the _parent_, non async version.

Args:
message: A message object.

Returns:
True if the message was posted successfully.
"""
if self._parent:
return self._parent._post_message_from_child_no_wait(message)
else:
return False

async def emit(self, message: Message) -> bool:
"""Send a message to the _parent_.

Args:
message: A message object.

Returns:
True if the message was posted successfully.
"""
if self._parent:
return await self._parent._post_message_from_child(message)
else:
return False

# TODO: Does dispatch_key belong on message pump?
async def dispatch_key(self, event: events.Key) -> bool:
"""Dispatch a key event to method.
Expand Down
8 changes: 5 additions & 3 deletions src/textual/scrollbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,12 @@ def _on_leave(self, event: events.Leave) -> None:
self.mouse_over = False

async def action_scroll_down(self) -> None:
await self.emit(ScrollDown(self) if self.vertical else ScrollRight(self))
await self.post_message(
ScrollDown(self) if self.vertical else ScrollRight(self)
)

async def action_scroll_up(self) -> None:
await self.emit(ScrollUp(self) if self.vertical else ScrollLeft(self))
await self.post_message(ScrollUp(self) if self.vertical else ScrollLeft(self))

def action_grab(self) -> None:
self.capture_mouse()
Expand Down Expand Up @@ -324,7 +326,7 @@ async def _on_mouse_move(self, event: events.MouseMove) -> None:
* (self.window_virtual_size / self.window_size)
)
)
await self.emit(ScrollTo(self, x=x, y=y))
await self.post_message(ScrollTo(self, x=x, y=y))
event.stop()

async def _on_click(self, event: events.Click) -> None:
Expand Down
4 changes: 2 additions & 2 deletions src/textual/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -2465,12 +2465,12 @@ def _on_enter(self, event: events.Enter) -> None:
def _on_focus(self, event: events.Focus) -> None:
self.has_focus = True
self.refresh()
self.emit_no_wait(events.DescendantFocus(self))
self.post_message_no_wait(events.DescendantFocus(self))

def _on_blur(self, event: events.Blur) -> None:
self.has_focus = False
self.refresh()
self.emit_no_wait(events.DescendantBlur(self))
self.post_message_no_wait(events.DescendantBlur(self))

def _on_descendant_blur(self, event: events.DescendantBlur) -> None:
if self._has_focus_within:
Expand Down
4 changes: 2 additions & 2 deletions src/textual/widgets/_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ def press(self) -> None:
# Manage the "active" effect:
self._start_active_affect()
# ...and let other components know that we've just been clicked:
self.emit_no_wait(Button.Pressed(self))
self.post_message_no_wait(Button.Pressed(self))

def _start_active_affect(self) -> None:
"""Start a small animation to show the button was clicked."""
Expand All @@ -267,7 +267,7 @@ def _start_active_affect(self) -> None:
async def _on_key(self, event: events.Key) -> None:
if event.key == "enter" and not self.disabled:
self._start_active_affect()
await self.emit(Button.Pressed(self))
await self.post_message(Button.Pressed(self))

@classmethod
def success(
Expand Down
6 changes: 3 additions & 3 deletions src/textual/widgets/_checkbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class Checkbox(Widget, can_focus=True):
"""The position of the slider."""

class Changed(Message, bubble=True):
"""Emitted when the status of the checkbox changes.
"""Posted when the status of the checkbox changes.

Can be handled using `on_checkbox_changed` in a subclass of `Checkbox`
or in a parent widget in the DOM.
Expand Down Expand Up @@ -122,7 +122,7 @@ def watch_value(self, value: bool) -> None:
self.animate("slider_pos", target_slider_pos, duration=0.3)
else:
self.slider_pos = target_slider_pos
self.emit_no_wait(self.Changed(self, self.value))
self.post_message_no_wait(self.Changed(self, self.value))

def watch_slider_pos(self, slider_pos: float) -> None:
self.set_class(slider_pos == 1, "-on")
Expand Down Expand Up @@ -151,5 +151,5 @@ def action_toggle(self) -> None:

def toggle(self) -> None:
"""Toggle the checkbox value. As a result of the value changing,
a Checkbox.Changed message will be emitted."""
a Checkbox.Changed message will be posted."""
self.value = not self.value
50 changes: 26 additions & 24 deletions src/textual/widgets/_data_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
hover_cell: Reactive[Coordinate] = Reactive(Coordinate(0, 0), repaint=False)

class CellHighlighted(Message, bubble=True):
"""Emitted when the cursor moves to highlight a new cell.
"""Posted when the cursor moves to highlight a new cell.
It's only relevant when the `cursor_type` is `"cell"`.
It's also emitted when the cell cursor is re-enabled (by setting `show_cursor=True`),
It's also posted when the cell cursor is re-enabled (by setting `show_cursor=True`),
and when the cursor type is changed to `"cell"`. Can be handled using
`on_data_table_cell_highlighted` in a subclass of `DataTable` or in a parent
widget in the DOM.
Expand All @@ -215,7 +215,7 @@ def __rich_repr__(self) -> rich.repr.Result:
yield "coordinate", self.coordinate

class CellSelected(Message, bubble=True):
"""Emitted by the `DataTable` widget when a cell is selected.
"""Posted by the `DataTable` widget when a cell is selected.
It's only relevant when the `cursor_type` is `"cell"`. Can be handled using
`on_data_table_cell_selected` in a subclass of `DataTable` or in a parent
widget in the DOM.
Expand All @@ -238,7 +238,7 @@ def __rich_repr__(self) -> rich.repr.Result:
yield "coordinate", self.coordinate

class RowHighlighted(Message, bubble=True):
"""Emitted when a row is highlighted. This message is only emitted when the
"""Posted when a row is highlighted. This message is only posted when the
`cursor_type` is set to `"row"`. Can be handled using `on_data_table_row_highlighted`
in a subclass of `DataTable` or in a parent widget in the DOM.

Expand All @@ -255,7 +255,7 @@ def __rich_repr__(self) -> rich.repr.Result:
yield "cursor_row", self.cursor_row

class RowSelected(Message, bubble=True):
"""Emitted when a row is selected. This message is only emitted when the
"""Posted when a row is selected. This message is only posted when the
`cursor_type` is set to `"row"`. Can be handled using
`on_data_table_row_selected` in a subclass of `DataTable` or in a parent
widget in the DOM.
Expand All @@ -273,7 +273,7 @@ def __rich_repr__(self) -> rich.repr.Result:
yield "cursor_row", self.cursor_row

class ColumnHighlighted(Message, bubble=True):
"""Emitted when a column is highlighted. This message is only emitted when the
"""Posted when a column is highlighted. This message is only posted when the
`cursor_type` is set to `"column"`. Can be handled using
`on_data_table_column_highlighted` in a subclass of `DataTable` or in a parent
widget in the DOM.
Expand All @@ -291,7 +291,7 @@ def __rich_repr__(self) -> rich.repr.Result:
yield "cursor_column", self.cursor_column

class ColumnSelected(Message, bubble=True):
"""Emitted when a column is selected. This message is only emitted when the
"""Posted when a column is selected. This message is only posted when the
`cursor_type` is set to `"column"`. Can be handled using
`on_data_table_column_selected` in a subclass of `DataTable` or in a parent
widget in the DOM.
Expand Down Expand Up @@ -405,7 +405,7 @@ def watch_show_cursor(self, show_cursor: bool) -> None:
self._clear_caches()
if show_cursor and self.cursor_type != "none":
# When we re-enable the cursor, apply highlighting and
# emit the appropriate [Row|Column|Cell]Highlighted event.
# post the appropriate [Row|Column|Cell]Highlighted event.
self._scroll_cursor_into_view(animate=False)
if self.cursor_type == "cell":
self._highlight_cell(self.cursor_cell)
Expand All @@ -431,7 +431,7 @@ def watch_cursor_cell(
self, old_coordinate: Coordinate, new_coordinate: Coordinate
) -> None:
if old_coordinate != new_coordinate:
# Refresh the old and the new cell, and emit the appropriate
# Refresh the old and the new cell, and post the appropriate
# message to tell users of the newly highlighted row/cell/column.
if self.cursor_type == "cell":
self.refresh_cell(*old_coordinate)
Expand All @@ -444,7 +444,7 @@ def watch_cursor_cell(
self._highlight_column(new_coordinate.column)

def _highlight_cell(self, coordinate: Coordinate) -> None:
"""Apply highlighting to the cell at the coordinate, and emit event."""
"""Apply highlighting to the cell at the coordinate, and post event."""
self.refresh_cell(*coordinate)
try:
cell_value = self.get_cell_value(coordinate)
Expand All @@ -453,19 +453,21 @@ def _highlight_cell(self, coordinate: Coordinate) -> None:
# In that case, there's nothing for us to do here.
return
else:
self.emit_no_wait(DataTable.CellHighlighted(self, cell_value, coordinate))
self.post_message_no_wait(
DataTable.CellHighlighted(self, cell_value, coordinate)
)

def _highlight_row(self, row_index: int) -> None:
"""Apply highlighting to the row at the given index, and emit event."""
"""Apply highlighting to the row at the given index, and post event."""
self.refresh_row(row_index)
if row_index in self.data:
self.emit_no_wait(DataTable.RowHighlighted(self, row_index))
self.post_message_no_wait(DataTable.RowHighlighted(self, row_index))

def _highlight_column(self, column_index: int) -> None:
"""Apply highlighting to the column at the given index, and emit event."""
"""Apply highlighting to the column at the given index, and post event."""
self.refresh_column(column_index)
if column_index < len(self.columns):
self.emit_no_wait(DataTable.ColumnHighlighted(self, column_index))
self.post_message_no_wait(DataTable.ColumnHighlighted(self, column_index))

def validate_cursor_cell(self, value: Coordinate) -> Coordinate:
return self._clamp_cursor_cell(value)
Expand Down Expand Up @@ -641,7 +643,7 @@ def add_row(self, *cells: CellType, height: int = 1) -> None:

# If a position has opened for the cursor to appear, where it previously
# could not (e.g. when there's no data in the table), then a highlighted
# event is emitted, since there's now a highlighted cell when there wasn't
# event is posted, since there's now a highlighted cell when there wasn't
# before.
cell_now_available = self.row_count == 1 and len(self.columns) > 0
visible_cursor = self.show_cursor and self.cursor_type != "none"
Expand Down Expand Up @@ -1039,8 +1041,8 @@ def _set_hover_cursor(self, active: bool) -> None:
def on_click(self, event: events.Click) -> None:
self._set_hover_cursor(True)
if self.show_cursor and self.cursor_type != "none":
# Only emit selection events if there is a visible row/col/cell cursor.
self._emit_selected_message()
# Only post selection events if there is a visible row/col/cell cursor.
self._post_message_selected_message()
meta = self.get_style_at(event.x, event.y).meta
if meta:
self.cursor_cell = Coordinate(meta["row"], meta["column"])
Expand Down Expand Up @@ -1088,14 +1090,14 @@ def action_cursor_left(self) -> None:
def action_select_cursor(self) -> None:
self._set_hover_cursor(False)
if self.show_cursor and self.cursor_type != "none":
self._emit_selected_message()
self._post_selected_message()

def _emit_selected_message(self):
"""Emit the appropriate message for a selection based on the `cursor_type`."""
def _post_selected_message(self):
"""Post the appropriate message for a selection based on the `cursor_type`."""
cursor_cell = self.cursor_cell
cursor_type = self.cursor_type
if cursor_type == "cell":
self.emit_no_wait(
self.post_message_no_wait(
DataTable.CellSelected(
self,
self.get_cell_value(cursor_cell),
Expand All @@ -1104,7 +1106,7 @@ def _emit_selected_message(self):
)
elif cursor_type == "row":
row, _ = cursor_cell
self.emit_no_wait(DataTable.RowSelected(self, row))
self.post_message_no_wait(DataTable.RowSelected(self, row))
elif cursor_type == "column":
_, column = cursor_cell
self.emit_no_wait(DataTable.ColumnSelected(self, column))
self.post_message_no_wait(DataTable.ColumnSelected(self, column))
6 changes: 3 additions & 3 deletions src/textual/widgets/_directory_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class DirectoryTree(Tree[DirEntry]):
"""

class FileSelected(Message, bubble=True):
"""Emitted when a file is selected.
"""Posted when a file is selected.

Can be handled using `on_directory_tree_file_selected` in a subclass of
`DirectoryTree` or in a parent widget in the DOM.
Expand Down Expand Up @@ -173,12 +173,12 @@ def on_tree_node_expanded(self, event: Tree.NodeSelected) -> None:
if not dir_entry.loaded:
self.load_directory(event.node)
else:
self.emit_no_wait(self.FileSelected(self, dir_entry.path))
self.post_message_no_wait(self.FileSelected(self, dir_entry.path))

def on_tree_node_selected(self, event: Tree.NodeSelected) -> None:
event.stop()
dir_entry = event.node.data
if dir_entry is None:
return
if not dir_entry.is_dir:
self.emit_no_wait(self.FileSelected(self, dir_entry.path))
self.post_message_no_wait(self.FileSelected(self, dir_entry.path))
8 changes: 4 additions & 4 deletions src/textual/widgets/_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class Input(Widget, can_focus=True):
max_size: reactive[int | None] = reactive(None)

class Changed(Message, bubble=True):
"""Emitted when the value changes.
"""Posted when the value changes.

Can be handled using `on_input_changed` in a subclass of `Input` or in a parent
widget in the DOM.
Expand All @@ -155,7 +155,7 @@ def __init__(self, sender: Input, value: str) -> None:
self.input: Input = sender

class Submitted(Message, bubble=True):
"""Emitted when the enter key is pressed within an `Input`.
"""Posted when the enter key is pressed within an `Input`.

Can be handled using `on_input_submitted` in a subclass of `Input` or in a
parent widget in the DOM.
Expand Down Expand Up @@ -244,7 +244,7 @@ def watch_cursor_position(self, cursor_position: int) -> None:
async def watch_value(self, value: str) -> None:
if self.styles.auto_dimensions:
self.refresh(layout=True)
await self.emit(self.Changed(self, value))
await self.post_message(self.Changed(self, value))

@property
def cursor_width(self) -> int:
Expand Down Expand Up @@ -479,4 +479,4 @@ def action_delete_left_all(self) -> None:
self.cursor_position = 0

async def action_submit(self) -> None:
await self.emit(self.Submitted(self, self.value))
await self.post_message(self.Submitted(self, self.value))
2 changes: 1 addition & 1 deletion src/textual/widgets/_list_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class _ChildClicked(Message):
pass

def on_click(self, event: events.Click) -> None:
self.emit_no_wait(self._ChildClicked(self))
self.post_message_no_wait(self._ChildClicked(self))

def watch_highlighted(self, value: bool) -> None:
self.set_class(value, "--highlight")
Loading