diff --git a/src/textual/app.py b/src/textual/app.py index ef9dbb84a..e93b2c51f 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -17,7 +17,7 @@ from . import events from . import actions from ._animator import Animator from .binding import Bindings, NoBinding -from .geometry import Point, Region +from .geometry import Offset, Region from . import log from ._context import active_app from ._event_broker import extract_handler_actions, NoHandler @@ -103,7 +103,7 @@ class App(MessagePump): self._action_targets = {"app", "view"} self._animator = Animator(self) self.animate = self._animator.bind(self) - self.mouse_position = Point(0, 0) + self.mouse_position = Offset(0, 0) self.bindings = Bindings() self._title = title @@ -370,7 +370,7 @@ class App(MessagePump): if isinstance(event, events.InputEvent): if isinstance(event, events.MouseEvent): - self.mouse_position = Point(event.x, event.y) + self.mouse_position = Offset(event.x, event.y) if isinstance(event, events.Key) and self.focused is not None: await self.focused.forward_event(event) await self.view.forward_event(event) diff --git a/src/textual/events.py b/src/textual/events.py index 3c8a25ca8..f9edeab39 100644 --- a/src/textual/events.py +++ b/src/textual/events.py @@ -5,7 +5,7 @@ from typing import Awaitable, Callable, Type, TYPE_CHECKING, TypeVar import rich.repr from rich.style import Style -from .geometry import Point, Dimensions +from .geometry import Offset, Dimensions from .message import Message from ._types import MessageTarget from .keys import Keys @@ -143,7 +143,7 @@ class MouseCapture(Event): """ - def __init__(self, sender: MessageTarget, mouse_position: Point) -> None: + def __init__(self, sender: MessageTarget, mouse_position: Offset) -> None: """ Args: @@ -161,7 +161,7 @@ class MouseCapture(Event): class MouseRelease(Event): """Mouse has been released.""" - def __init__(self, sender: MessageTarget, mouse_position: Point) -> None: + def __init__(self, sender: MessageTarget, mouse_position: Offset) -> None: """ Args: sender (MessageTarget): The sender of the event, (in this case the app). diff --git a/src/textual/geometry.py b/src/textual/geometry.py index 1d55b7e54..ead7fa969 100644 --- a/src/textual/geometry.py +++ b/src/textual/geometry.py @@ -25,7 +25,7 @@ def clamp(value: T, minimum: T, maximum: T) -> T: return value -class Point(NamedTuple): +class Offset(NamedTuple): """A point defined by x and y coordinates.""" x: int @@ -36,21 +36,21 @@ class Point(NamedTuple): """Check if the point is at the origin (0, 0)""" return self == (0, 0) - def __add__(self, other: object) -> Point: + def __add__(self, other: object) -> Offset: if isinstance(other, tuple): _x, _y = self x, y = other - return Point(_x + x, _y + y) + return Offset(_x + x, _y + y) return NotImplemented - def __sub__(self, other: object) -> Point: + def __sub__(self, other: object) -> Offset: if isinstance(other, tuple): _x, _y = self x, y = other - return Point(_x - x, _y - y) + return Offset(_x - x, _y - y) return NotImplemented - def blend(self, destination: Point, factor: float) -> Point: + def blend(self, destination: Offset, factor: float) -> Offset: """Blend (interpolate) to a new point. Args: @@ -62,7 +62,7 @@ class Point(NamedTuple): """ x1, y1 = self x2, y2 = destination - return Point(int(x1 + (x2 - x1) * factor), int((y1 + (y2 - y1) * factor))) + return Offset(int(x1 + (x2 - x1) * factor), int((y1 + (y2 - y1) * factor))) class Dimensions(NamedTuple): @@ -173,9 +173,9 @@ class Region(NamedTuple): return self.width * self.height @property - def origin(self) -> Point: + def origin(self) -> Offset: """Get the start point of the region.""" - return Point(self.x, self.y) + return Offset(self.x, self.y) @property def size(self) -> Dimensions: diff --git a/src/textual/layout.py b/src/textual/layout.py index 7ba4ce3be..76e59eef9 100644 --- a/src/textual/layout.py +++ b/src/textual/layout.py @@ -20,7 +20,7 @@ from ._loop import loop_last from .layout_map import LayoutMap from ._types import Lines -from .geometry import clamp, Region, Point, Dimensions +from .geometry import clamp, Region, Offset, Dimensions PY38 = sys.version_info >= (3, 8) @@ -191,7 +191,7 @@ class Layout(ABC): for widget, (region, _order, clip) in layers: yield widget, region.intersection(clip) - def get_offset(self, widget: Widget) -> Point: + def get_offset(self, widget: Widget) -> Offset: try: return self.map[widget].region.origin except KeyError: diff --git a/src/textual/layouts/grid.py b/src/textual/layouts/grid.py index 48363a095..b3ce81b44 100644 --- a/src/textual/layouts/grid.py +++ b/src/textual/layouts/grid.py @@ -11,7 +11,7 @@ from typing import Iterable, NamedTuple from rich.console import Console from .._layout_resolve import layout_resolve -from ..geometry import Dimensions, Point, Region +from ..geometry import Dimensions, Offset, Region from ..layout import Layout from ..layout_map import LayoutMap from ..widget import Widget @@ -369,7 +369,7 @@ class GridLayout(Layout): } order = 1 from_corners = Region.from_corners - gutter = Point(self.column_gutter, self.row_gutter) + gutter = Offset(self.column_gutter, self.row_gutter) for widget, area in widget_areas: column_start, column_end, row_start, row_end = self.areas[area] try: diff --git a/src/textual/layouts/vertical.py b/src/textual/layouts/vertical.py index 709af4179..3677fa80b 100644 --- a/src/textual/layouts/vertical.py +++ b/src/textual/layouts/vertical.py @@ -5,7 +5,7 @@ from typing import Iterable from rich.console import Console -from ..geometry import Point, Region, Dimensions +from ..geometry import Offset, Region, Dimensions from ..layout import Layout from ..layout_map import LayoutMap from ..widget import Widget diff --git a/src/textual/page.py b/src/textual/page.py index 630ec9f8e..6816055c9 100644 --- a/src/textual/page.py +++ b/src/textual/page.py @@ -7,7 +7,7 @@ from rich.padding import Padding, PaddingDimensions from rich.segment import Segment from rich.style import StyleType -from .geometry import Dimensions, Point +from .geometry import Dimensions, Offset from .message import Message from .widget import Widget, Reactive @@ -35,14 +35,14 @@ class PageRender: self.height = height self.style = style self.padding = padding - self.offset = Point(0, 0) + self.offset = Offset(0, 0) self._render_width: int | None = None self._render_height: int | None = None self.size = Dimensions(0, 0) self._lines: list[list[Segment]] = [] def move_to(self, x: int = 0, y: int = 0) -> None: - self.offset = Point(x, y) + self.offset = Offset(x, y) def clear(self) -> None: self._render_width = None @@ -112,11 +112,11 @@ class Page(Widget): async def watch_scroll_x(self, new: int) -> None: x, y = self._page.offset - self._page.offset = Point(new, y) + self._page.offset = Offset(new, y) async def watch_scroll_y(self, new: int) -> None: x, y = self._page.offset - self._page.offset = Point(x, new) + self._page.offset = Offset(x, new) def update(self, renderable: RenderableType | None = None) -> None: if renderable: diff --git a/src/textual/screen_update.py b/src/textual/screen_update.py index 4814187c8..487d7094a 100644 --- a/src/textual/screen_update.py +++ b/src/textual/screen_update.py @@ -6,7 +6,7 @@ from rich.console import Console, RenderableType from rich.control import Control from rich.segment import Segment, Segments -from .geometry import Point +from .geometry import Offset from ._loop import loop_last @@ -18,7 +18,7 @@ class ScreenUpdate: self.lines = console.render_lines( renderable, console.options.update_dimensions(width, height) ) - self.offset = Point(0, 0) + self.offset = Offset(0, 0) def render(self, x: int, y: int) -> Iterable[Segment]: move_to = Control.move_to diff --git a/src/textual/scrollbar.py b/src/textual/scrollbar.py index ca0671cc5..cfa69dabc 100644 --- a/src/textual/scrollbar.py +++ b/src/textual/scrollbar.py @@ -7,7 +7,7 @@ from rich.segment import Segment, Segments from rich.style import Style, StyleType from . import events -from .geometry import Point +from .geometry import Offset from ._types import MessageTarget from .message import Message from .widget import Reactive, Widget @@ -184,7 +184,7 @@ class ScrollBar(Widget): window_size: Reactive[int] = Reactive(0) position: Reactive[int] = Reactive(0) mouse_over: Reactive[bool] = Reactive(False) - grabbed: Reactive[Point | None] = Reactive(None) + grabbed: Reactive[Offset | None] = Reactive(None) def __rich_repr__(self) -> rich.repr.RichReprResult: yield "virtual_size", self.virtual_size diff --git a/src/textual/view.py b/src/textual/view.py index 66bb9fe44..b57466186 100644 --- a/src/textual/view.py +++ b/src/textual/view.py @@ -10,7 +10,7 @@ from rich.style import Style from . import events from . import log from .layout import Layout, NoWidget -from .geometry import Dimensions, Point, Region +from .geometry import Dimensions, Offset, Region from .messages import UpdateMessage, LayoutMessage from .reactive import Reactive, watch @@ -53,8 +53,8 @@ class View(Widget): scroll_y: Reactive[int] = Reactive(0) @property - def scroll_offset(self) -> Point: - return Point(self.scroll_x, self.scroll_y) + def scroll_offset(self) -> Offset: + return Offset(self.scroll_x, self.scroll_y) @property def virtual_size(self) -> Dimensions: @@ -116,7 +116,7 @@ class View(Widget): def render(self) -> RenderableType: return self.layout - def get_offset(self, widget: Widget) -> Point: + def get_offset(self, widget: Widget) -> Offset: return self.layout.get_offset(widget) def check_layout(self) -> bool: diff --git a/tests/test_geometry.py b/tests/test_geometry.py index 9df876d8c..cfe94fc74 100644 --- a/tests/test_geometry.py +++ b/tests/test_geometry.py @@ -1,6 +1,6 @@ import pytest -from textual.geometry import clamp, Point, Dimensions, Region +from textual.geometry import clamp, Offset, Dimensions, Region def test_dimensions_region(): @@ -18,13 +18,13 @@ def test_dimensions_contains(): def test_dimensions_contains_point(): - assert Dimensions(10, 10).contains_point(Point(5, 5)) - assert Dimensions(10, 10).contains_point(Point(9, 9)) - assert Dimensions(10, 10).contains_point(Point(0, 0)) - assert not Dimensions(10, 10).contains_point(Point(10, 9)) - assert not Dimensions(10, 10).contains_point(Point(9, 10)) - assert not Dimensions(10, 10).contains_point(Point(-1, 0)) - assert not Dimensions(10, 10).contains_point(Point(0, -1)) + assert Dimensions(10, 10).contains_point(Offset(5, 5)) + assert Dimensions(10, 10).contains_point(Offset(9, 9)) + assert Dimensions(10, 10).contains_point(Offset(0, 0)) + assert not Dimensions(10, 10).contains_point(Offset(10, 9)) + assert not Dimensions(10, 10).contains_point(Offset(9, 10)) + assert not Dimensions(10, 10).contains_point(Offset(-1, 0)) + assert not Dimensions(10, 10).contains_point(Offset(0, -1)) def test_dimensions_contains_special(): @@ -63,32 +63,32 @@ def test_clamp(): def test_point_is_origin(): - assert Point(0, 0).is_origin - assert not Point(1, 0).is_origin + assert Offset(0, 0).is_origin + assert not Offset(1, 0).is_origin def test_point_add(): - assert Point(1, 1) + Point(2, 2) == Point(3, 3) - assert Point(1, 2) + Point(3, 4) == Point(4, 6) + assert Offset(1, 1) + Offset(2, 2) == Offset(3, 3) + assert Offset(1, 2) + Offset(3, 4) == Offset(4, 6) with pytest.raises(TypeError): - Point(1, 1) + "foo" + Offset(1, 1) + "foo" def test_point_sub(): - assert Point(1, 1) - Point(2, 2) == Point(-1, -1) - assert Point(3, 4) - Point(2, 1) == Point(1, 3) + assert Offset(1, 1) - Offset(2, 2) == Offset(-1, -1) + assert Offset(3, 4) - Offset(2, 1) == Offset(1, 3) with pytest.raises(TypeError): - Point(1, 1) - "foo" + Offset(1, 1) - "foo" def test_point_blend(): - assert Point(1, 2).blend(Point(3, 4), 0) == Point(1, 2) - assert Point(1, 2).blend(Point(3, 4), 1) == Point(3, 4) - assert Point(1, 2).blend(Point(3, 4), 0.5) == Point(2, 3) + assert Offset(1, 2).blend(Offset(3, 4), 0) == Offset(1, 2) + assert Offset(1, 2).blend(Offset(3, 4), 1) == Offset(3, 4) + assert Offset(1, 2).blend(Offset(3, 4), 0.5) == Offset(2, 3) def test_region_from_origin(): - assert Region.from_origin(Point(3, 4), (5, 6)) == Region(3, 4, 5, 6) + assert Region.from_origin(Offset(3, 4), (5, 6)) == Region(3, 4, 5, 6) def test_region_area(): @@ -102,7 +102,7 @@ def test_region_size(): def test_region_origin(): - assert Region(1, 2, 3, 4).origin == Point(1, 2) + assert Region(1, 2, 3, 4).origin == Offset(1, 2) def test_region_add():