127 lines
4.8 KiB
Python
127 lines
4.8 KiB
Python
"""Enhanced DataTable with improved keyboard navigation."""
|
|
|
|
from typing import Any
|
|
|
|
from textual import events
|
|
from textual.binding import Binding
|
|
from textual.message import Message
|
|
from textual.widgets import DataTable
|
|
|
|
|
|
class EnhancedDataTable(DataTable[Any]):
|
|
"""DataTable with enhanced keyboard navigation and visual feedback."""
|
|
|
|
BINDINGS = [
|
|
Binding("up,k", "cursor_up", "Cursor Up", show=False),
|
|
Binding("down,j", "cursor_down", "Cursor Down", show=False),
|
|
Binding("left,h", "cursor_left", "Cursor Left", show=False),
|
|
Binding("right,l", "cursor_right", "Cursor Right", show=False),
|
|
Binding("home", "cursor_home", "First Row", show=False),
|
|
Binding("end", "cursor_end", "Last Row", show=False),
|
|
Binding("pageup", "page_up", "Page Up", show=False),
|
|
Binding("pagedown", "page_down", "Page Down", show=False),
|
|
Binding("enter", "select_cursor", "Select", show=False),
|
|
Binding("space", "toggle_selection", "Toggle Selection", show=False),
|
|
Binding("ctrl+a", "select_all", "Select All", show=False),
|
|
Binding("ctrl+shift+a", "clear_selection", "Clear Selection", show=False),
|
|
]
|
|
|
|
def __init__(self, **kwargs: Any) -> None:
|
|
super().__init__(**kwargs)
|
|
self.cursor_type = "row" # Default to row selection
|
|
self.zebra_stripes = True # Enable zebra striping for better visibility
|
|
self.show_cursor = True
|
|
|
|
def on_key(self, event: events.Key) -> None:
|
|
"""Handle additional keyboard shortcuts."""
|
|
if event.key == "ctrl+1":
|
|
# Jump to first column
|
|
self.move_cursor(column=0)
|
|
event.prevent_default()
|
|
elif event.key == "ctrl+9":
|
|
# Jump to last column
|
|
if self.columns:
|
|
self.move_cursor(column=len(self.columns) - 1)
|
|
event.prevent_default()
|
|
elif event.key == "/":
|
|
# Start quick search (to be implemented by parent)
|
|
self.post_message(self.QuickSearch(self))
|
|
event.prevent_default()
|
|
elif event.key == "escape":
|
|
# Clear selection or exit search
|
|
# Clear selection by calling action
|
|
self.action_clear_selection()
|
|
event.prevent_default()
|
|
# No else clause needed - just handle our events
|
|
|
|
def action_cursor_home(self) -> None:
|
|
"""Move cursor to first row."""
|
|
if self.row_count > 0:
|
|
self.move_cursor(row=0)
|
|
|
|
def action_cursor_end(self) -> None:
|
|
"""Move cursor to last row."""
|
|
if self.row_count > 0:
|
|
self.move_cursor(row=self.row_count - 1)
|
|
|
|
def action_page_up(self) -> None:
|
|
"""Move cursor up by visible page size."""
|
|
if self.row_count > 0:
|
|
page_size = max(1, self.size.height // 2) # Approximate visible rows
|
|
new_row = max(0, self.cursor_coordinate.row - page_size)
|
|
self.move_cursor(row=new_row)
|
|
|
|
def action_page_down(self) -> None:
|
|
"""Move cursor down by visible page size."""
|
|
if self.row_count > 0:
|
|
page_size = max(1, self.size.height // 2) # Approximate visible rows
|
|
new_row = min(self.row_count - 1, self.cursor_coordinate.row + page_size)
|
|
self.move_cursor(row=new_row)
|
|
|
|
def action_toggle_selection(self) -> None:
|
|
"""Toggle selection of current row."""
|
|
if self.row_count > 0:
|
|
current_row = self.cursor_coordinate.row
|
|
# This will be handled by the parent screen
|
|
self.post_message(self.RowToggled(self, current_row))
|
|
|
|
def action_select_all(self) -> None:
|
|
"""Select all rows."""
|
|
# This will be handled by the parent screen
|
|
self.post_message(self.SelectAll(self))
|
|
|
|
def action_clear_selection(self) -> None:
|
|
"""Clear all selections."""
|
|
# This will be handled by the parent screen
|
|
self.post_message(self.ClearSelection(self))
|
|
|
|
# Custom messages for enhanced functionality
|
|
class QuickSearch(Message):
|
|
"""Posted when user wants to start a quick search."""
|
|
|
|
def __init__(self, table: "EnhancedDataTable") -> None:
|
|
super().__init__()
|
|
self.table = table
|
|
|
|
class RowToggled(Message):
|
|
"""Posted when a row selection is toggled."""
|
|
|
|
def __init__(self, table: "EnhancedDataTable", row_index: int) -> None:
|
|
super().__init__()
|
|
self.table = table
|
|
self.row_index = row_index
|
|
|
|
class SelectAll(Message):
|
|
"""Posted when user wants to select all rows."""
|
|
|
|
def __init__(self, table: "EnhancedDataTable") -> None:
|
|
super().__init__()
|
|
self.table = table
|
|
|
|
class ClearSelection(Message):
|
|
"""Posted when user wants to clear selection."""
|
|
|
|
def __init__(self, table: "EnhancedDataTable") -> None:
|
|
super().__init__()
|
|
self.table = table
|