mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
checker 4 and diagram
This commit is contained in:
108
docs/examples/guide/widgets/checker04.py
Normal file
108
docs/examples/guide/widgets/checker04.py
Normal file
@@ -0,0 +1,108 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from textual import events
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.geometry import Offset, Region, Size
|
||||
from textual.reactive import var
|
||||
from textual.strip import Strip
|
||||
from textual.scroll_view import ScrollView
|
||||
|
||||
from rich.segment import Segment
|
||||
from rich.style import Style
|
||||
|
||||
|
||||
class CheckerBoard(ScrollView):
|
||||
COMPONENT_CLASSES = {
|
||||
"checkerboard--white-square",
|
||||
"checkerboard--black-square",
|
||||
"checkerboard--cursor-square",
|
||||
}
|
||||
|
||||
DEFAULT_CSS = """
|
||||
CheckerBoard > .checkerboard--white-square {
|
||||
background: #A5BAC9;
|
||||
}
|
||||
CheckerBoard > .checkerboard--black-square {
|
||||
background: #004578;
|
||||
}
|
||||
CheckerBoard > .checkerboard--cursor-square {
|
||||
background: darkred
|
||||
}
|
||||
"""
|
||||
|
||||
cursor_square: var[Offset | None] = var(None)
|
||||
|
||||
def __init__(self, board_size: int) -> None:
|
||||
super().__init__()
|
||||
self.board_size = board_size
|
||||
# Each square is 4 rows and 8 columns
|
||||
self.virtual_size = Size(board_size * 8, board_size * 4)
|
||||
|
||||
def on_mouse_move(self, event: events.MouseMove) -> None:
|
||||
"""Called when the user moves the mouse over the widget."""
|
||||
mouse_position = event.offset + self.scroll_offset
|
||||
self.cursor_square = Offset(mouse_position.x // 8, mouse_position.y // 4)
|
||||
|
||||
def watch_cursor_square(
|
||||
self, previous_square: Offset | None, cursor_square: Offset | None
|
||||
) -> None:
|
||||
"""Called when the cursor square changes."""
|
||||
|
||||
def get_square_region(square_offset: Offset) -> Region:
|
||||
"""Get region relative to widget from square coordinate."""
|
||||
x, y = square_offset
|
||||
region = Region(x * 8, y * 4, 8, 4)
|
||||
# Move the region in to the widgets frame of reference
|
||||
region = region.translate(-self.scroll_offset)
|
||||
return region
|
||||
|
||||
# Refresh the previous cursor square
|
||||
if previous_square is not None:
|
||||
self.refresh(get_square_region(previous_square))
|
||||
|
||||
# Refresh the new cursor square
|
||||
if cursor_square is not None:
|
||||
self.refresh(get_square_region(cursor_square))
|
||||
|
||||
def render_line(self, y: int) -> Strip:
|
||||
"""Render a line of the widget. y is relative to the top of the widget."""
|
||||
|
||||
scroll_x, scroll_y = self.scroll_offset # The current scroll position
|
||||
y += scroll_y # The line at the top of the widget is now `scroll_y`, not zero!
|
||||
row_index = y // 4 # four lines per row
|
||||
|
||||
white = self.get_component_rich_style("checkerboard--white-square")
|
||||
black = self.get_component_rich_style("checkerboard--black-square")
|
||||
cursor = self.get_component_rich_style("checkerboard--cursor-square")
|
||||
|
||||
if row_index >= self.board_size:
|
||||
return Strip.blank(self.size.width)
|
||||
|
||||
is_odd = row_index % 2
|
||||
|
||||
def get_square_style(column: int, row: int) -> Style:
|
||||
"""Get the cursor style at the given position on the checkerboard."""
|
||||
if self.cursor_square == Offset(column, row):
|
||||
square_style = cursor
|
||||
else:
|
||||
square_style = black if (column + is_odd) % 2 else white
|
||||
return square_style
|
||||
|
||||
segments = [
|
||||
Segment(" " * 8, get_square_style(column, row_index))
|
||||
for column in range(self.board_size)
|
||||
]
|
||||
strip = Strip(segments, self.board_size * 8)
|
||||
# Crop the strip so that is covers the visible area
|
||||
strip = strip.crop(scroll_x, scroll_x + self.size.width)
|
||||
return strip
|
||||
|
||||
|
||||
class BoardApp(App):
|
||||
def compose(self) -> ComposeResult:
|
||||
yield CheckerBoard(100)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = BoardApp()
|
||||
app.run()
|
||||
Reference in New Issue
Block a user