mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Option to ensure scroll_to_center doesn't scroll so as to hide the top left corner of the widget (#2682)
* Option to ensure origin of widget is visible when calling scroll to center * Update CHANGELOG.md --------- Co-authored-by: Will McGugan <willmcgugan@gmail.com>
This commit is contained in:
@@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- `work` decorator accepts `description` parameter to add debug string https://github.com/Textualize/textual/issues/2597
|
- `work` decorator accepts `description` parameter to add debug string https://github.com/Textualize/textual/issues/2597
|
||||||
- Added `SelectionList` widget https://github.com/Textualize/textual/pull/2652
|
- Added `SelectionList` widget https://github.com/Textualize/textual/pull/2652
|
||||||
- `App.AUTO_FOCUS` to set auto focus on all screens https://github.com/Textualize/textual/issues/2594
|
- `App.AUTO_FOCUS` to set auto focus on all screens https://github.com/Textualize/textual/issues/2594
|
||||||
|
- Option to `scroll_to_center` to ensure we don't scroll such that the top left corner of the widget is not visible https://github.com/Textualize/textual/pull/2682
|
||||||
- Added `Widget.tooltip` property https://github.com/Textualize/textual/pull/2670
|
- Added `Widget.tooltip` property https://github.com/Textualize/textual/pull/2670
|
||||||
- Added `Region.inflect` https://github.com/Textualize/textual/pull/2670
|
- Added `Region.inflect` https://github.com/Textualize/textual/pull/2670
|
||||||
- `Suggester` API to compose with widgets for automatic suggestions https://github.com/Textualize/textual/issues/2330
|
- `Suggester` API to compose with widgets for automatic suggestions https://github.com/Textualize/textual/issues/2330
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ class Screen(Generic[ScreenResultType], Widget):
|
|||||||
def scroll_to_center(widget: Widget) -> None:
|
def scroll_to_center(widget: Widget) -> None:
|
||||||
"""Scroll to center (after a refresh)."""
|
"""Scroll to center (after a refresh)."""
|
||||||
if widget.has_focus and not self.screen.can_view(widget):
|
if widget.has_focus and not self.screen.can_view(widget):
|
||||||
self.screen.scroll_to_center(widget)
|
self.screen.scroll_to_center(widget, origin_visible=True)
|
||||||
|
|
||||||
self.call_after_refresh(scroll_to_center, widget)
|
self.call_after_refresh(scroll_to_center, widget)
|
||||||
widget.post_message(events.Focus())
|
widget.post_message(events.Focus())
|
||||||
|
|||||||
@@ -2406,7 +2406,7 @@ class Widget(DOMNode):
|
|||||||
force=force,
|
force=force,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _scroll_to_center_of(
|
async def _scroll_widget_to_center_of_self(
|
||||||
self,
|
self,
|
||||||
widget: Widget,
|
widget: Widget,
|
||||||
animate: bool = True,
|
animate: bool = True,
|
||||||
@@ -2415,8 +2415,11 @@ class Widget(DOMNode):
|
|||||||
duration: float | None = None,
|
duration: float | None = None,
|
||||||
easing: EasingFunction | str | None = None,
|
easing: EasingFunction | str | None = None,
|
||||||
force: bool = False,
|
force: bool = False,
|
||||||
|
origin_visible: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Scroll a widget to the center of this container.
|
"""Scroll a widget to the center of this container. Note that this may
|
||||||
|
result in more than one container scrolling, since multiple containers
|
||||||
|
might be encountered on the path from `widget` to `self`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
widget: The widget to center.
|
widget: The widget to center.
|
||||||
@@ -2425,6 +2428,7 @@ class Widget(DOMNode):
|
|||||||
duration: Duration of animation, if `animate` is `True` and `speed` is `None`.
|
duration: Duration of animation, if `animate` is `True` and `speed` is `None`.
|
||||||
easing: An easing method for the scrolling animation.
|
easing: An easing method for the scrolling animation.
|
||||||
force: Force scrolling even when prohibited by overflow styling.
|
force: Force scrolling even when prohibited by overflow styling.
|
||||||
|
origin_visible: Ensure that the top left corner of the widget remains visible after the scroll.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
central_point = Offset(
|
central_point = Offset(
|
||||||
@@ -2435,6 +2439,9 @@ class Widget(DOMNode):
|
|||||||
container = widget.parent
|
container = widget.parent
|
||||||
while isinstance(container, Widget) and widget is not self:
|
while isinstance(container, Widget) and widget is not self:
|
||||||
container_virtual_region = container.virtual_region
|
container_virtual_region = container.virtual_region
|
||||||
|
if origin_visible and widget.region.height > container.region.height:
|
||||||
|
target_region = widget.virtual_region
|
||||||
|
else:
|
||||||
# The region we want to scroll to must be centered around the central point.
|
# The region we want to scroll to must be centered around the central point.
|
||||||
# We make it as big as possible because `scroll_to_region` scrolls as little
|
# We make it as big as possible because `scroll_to_region` scrolls as little
|
||||||
# as possible.
|
# as possible.
|
||||||
@@ -2444,6 +2451,7 @@ class Widget(DOMNode):
|
|||||||
container_virtual_region.width,
|
container_virtual_region.width,
|
||||||
container_virtual_region.height,
|
container_virtual_region.height,
|
||||||
)
|
)
|
||||||
|
|
||||||
scroll = container.scroll_to_region(
|
scroll = container.scroll_to_region(
|
||||||
target_region,
|
target_region,
|
||||||
animate=animate,
|
animate=animate,
|
||||||
@@ -2480,25 +2488,31 @@ class Widget(DOMNode):
|
|||||||
duration: float | None = None,
|
duration: float | None = None,
|
||||||
easing: EasingFunction | str | None = None,
|
easing: EasingFunction | str | None = None,
|
||||||
force: bool = False,
|
force: bool = False,
|
||||||
|
origin_visible: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Scroll this widget to the center of the screen.
|
"""Scroll this widget to the center of self.
|
||||||
|
|
||||||
|
The center of the widget will be scrolled to the center of the container.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
widget: The widget to scroll to the center of self.
|
||||||
animate: Whether to animate the scroll.
|
animate: Whether to animate the scroll.
|
||||||
speed: Speed of scroll if animate is `True`; or `None` to use `duration`.
|
speed: Speed of scroll if animate is `True`; or `None` to use `duration`.
|
||||||
duration: Duration of animation, if `animate` is `True` and `speed` is `None`.
|
duration: Duration of animation, if `animate` is `True` and `speed` is `None`.
|
||||||
easing: An easing method for the scrolling animation.
|
easing: An easing method for the scrolling animation.
|
||||||
force: Force scrolling even when prohibited by overflow styling.
|
force: Force scrolling even when prohibited by overflow styling.
|
||||||
|
origin_visible: Ensure that the top left corner of the widget remains visible after the scroll.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.call_after_refresh(
|
self.call_after_refresh(
|
||||||
self._scroll_to_center_of,
|
self._scroll_widget_to_center_of_self,
|
||||||
widget=widget,
|
widget=widget,
|
||||||
animate=animate,
|
animate=animate,
|
||||||
speed=speed,
|
speed=speed,
|
||||||
duration=duration,
|
duration=duration,
|
||||||
easing=easing,
|
easing=easing,
|
||||||
force=force,
|
force=force,
|
||||||
|
origin_visible=origin_visible,
|
||||||
)
|
)
|
||||||
|
|
||||||
def can_view(self, widget: Widget) -> bool:
|
def can_view(self, widget: Widget) -> bool:
|
||||||
|
|||||||
Reference in New Issue
Block a user