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

DataTable - Message emitted when header selected #1788

Merged
merged 10 commits into from
Feb 14, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added `DataTable.get_row_at` to retrieve the values from a row by index https://github.com/Textualize/textual/pull/1786
- Added `DataTable.get_column` to retrieve the values from a column by key https://github.com/Textualize/textual/pull/1786
- Added `DataTable.get_column_at` to retrieve the values from a column by index https://github.com/Textualize/textual/pull/1786
- Added `DataTable.HeaderSelected` which is posted when header label clicked https://github.com/Textualize/textual/pull/1788
- Added `DOMNode.watch` and `DOMNode.is_attached` methods https://github.com/Textualize/textual/pull/1750
- Added `DOMNode.css_tree` which is a renderable that shows the DOM and CSS https://github.com/Textualize/textual/pull/1778
- Added `DOMNode.children_view` which is a view on to a nodes children list, use for querying https://github.com/Textualize/textual/pull/1778
Expand Down
2 changes: 2 additions & 0 deletions docs/widgets/data_table.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ The example below populates a table with CSV data.

### ::: textual.widgets.DataTable.ColumnSelected

### ::: textual.widgets.DataTable.HeaderSelected

## Bindings

The data table widget defines directly the following bindings:
Expand Down
1 change: 0 additions & 1 deletion src/textual/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

if TYPE_CHECKING:
from .message_pump import MessagePump
from .widget import Widget


@rich.repr.auto
Expand Down
52 changes: 43 additions & 9 deletions src/textual/widgets/_data_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,29 @@ def __rich_repr__(self) -> rich.repr.Result:
yield "cursor_column", self.cursor_column
yield "column_key", self.column_key

class HeaderSelected(Message, bubble=True):
"""Posted when a column header/label is clicked."""

def __init__(
self,
sender: DataTable,
column_key: ColumnKey,
column_index: int,
label: Text,
):
self.column_key = column_key
"""The key for the column."""
self.column_index = column_index
"""The index for the column."""
self.label = label
"""The text of the label."""
super().__init__(sender)

def __rich_repr__(self) -> rich.repr.Result:
yield "sender", self.sender
yield "column_key", self.column_key
yield "label", self.label.plain

def __init__(
self,
*,
Expand Down Expand Up @@ -1334,8 +1357,7 @@ def _render_cell(
column_key = self._column_locations.get_key(column_index)
cell_cache_key = (row_key, column_key, style, cursor, hover, self._update_count)
if cell_cache_key not in self._cell_render_cache:
if not is_header_row:
style += Style.from_meta({"row": row_index, "column": column_index})
style += Style.from_meta({"row": row_index, "column": column_index})
height = self.header_height if is_header_row else self.rows[row_key].height
cell = self._get_row_renderables(row_index)[column_index]
lines = self.app.console.render_lines(
Expand Down Expand Up @@ -1650,14 +1672,26 @@ 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":
meta = self.get_style_at(event.x, event.y).meta
if not meta:
return

row_index = meta["row"]
column_index = meta["column"]
is_header_click = self.show_header and row_index == -1
if is_header_click:
# Header clicks work even if cursor is off, and doesn't move the cursor.
column = self.ordered_columns[column_index]
message = DataTable.HeaderSelected(
self, column.key, column_index, label=column.label
)
self.post_message_no_wait(message)
elif self.show_cursor and self.cursor_type != "none":
# Only post selection events if there is a visible row/col/cell cursor.
meta = self.get_style_at(event.x, event.y).meta
if meta:
self.cursor_coordinate = Coordinate(meta["row"], meta["column"])
self._post_selected_message()
self._scroll_cursor_into_view(animate=True)
event.stop()
self.cursor_coordinate = Coordinate(row_index, column_index)
self._post_selected_message()
self._scroll_cursor_into_view(animate=True)
event.stop()

def action_cursor_up(self) -> None:
self._set_hover_cursor(False)
Expand Down
Loading