@@ -2260,7 +2260,9 @@ def scroll_to_widget(
22602260 speed : float | None = None ,
22612261 duration : float | None = None ,
22622262 easing : EasingFunction | str | None = None ,
2263+ center : bool = False ,
22632264 top : bool = False ,
2265+ origin_visible : bool = True ,
22642266 force : bool = False ,
22652267 ) -> bool :
22662268 """Scroll scrolling to bring a widget in to view.
@@ -2272,6 +2274,7 @@ def scroll_to_widget(
22722274 duration: Duration of animation, if `animate` is `True` and `speed` is `None`.
22732275 easing: An easing method for the scrolling animation.
22742276 top: Scroll widget to top of container.
2277+ origin_visible: Ensure that the top left of the widget is within the window.
22752278 force: Force scrolling even when prohibited by overflow styling.
22762279
22772280 Returns:
@@ -2293,8 +2296,10 @@ def scroll_to_widget(
22932296 animate = animate ,
22942297 speed = speed ,
22952298 duration = duration ,
2299+ center = center ,
22962300 top = top ,
22972301 easing = easing ,
2302+ origin_visible = origin_visible ,
22982303 force = force ,
22992304 )
23002305 if scroll_offset :
@@ -2325,7 +2330,9 @@ def scroll_to_region(
23252330 speed : float | None = None ,
23262331 duration : float | None = None ,
23272332 easing : EasingFunction | str | None = None ,
2333+ center : bool = False ,
23282334 top : bool = False ,
2335+ origin_visible : bool = True ,
23292336 force : bool = False ,
23302337 ) -> Offset :
23312338 """Scrolls a given region in to view, if required.
@@ -2341,6 +2348,7 @@ def scroll_to_region(
23412348 duration: Duration of animation, if `animate` is `True` and `speed` is `None`.
23422349 easing: An easing method for the scrolling animation.
23432350 top: Scroll `region` to top of container.
2351+ origin_visible: Ensure that the top left of the widget is within the window.
23442352 force: Force scrolling even when prohibited by overflow styling.
23452353
23462354 Returns:
@@ -2350,11 +2358,28 @@ def scroll_to_region(
23502358 if spacing is not None :
23512359 window = window .shrink (spacing )
23522360
2353- if window in region and not top :
2361+ if window in region and not ( top or center ) :
23542362 return Offset ()
23552363
2356- delta_x , delta_y = Region .get_scroll_to_visible (window , region , top = top )
2364+ if center :
2365+ region_center_x , region_center_y = region .center
2366+ window_center_x , window_center_y = window .center
2367+ center_delta = Offset (
2368+ round (region_center_x - window_center_x ),
2369+ round (region_center_y - window_center_y ),
2370+ )
2371+ if origin_visible and region .offset not in window .translate (center_delta ):
2372+ center_delta = Region .get_scroll_to_visible (window , region , top = True )
2373+ delta_x , delta_y = center_delta
2374+ else :
2375+ delta_x , delta_y = Region .get_scroll_to_visible (window , region , top = top )
23572376 scroll_x , scroll_y = self .scroll_offset
2377+
2378+ if not self .allow_horizontal_scroll and not force :
2379+ delta_x = 0
2380+ if not self .allow_vertical_scroll and not force :
2381+ delta_y = 0
2382+
23582383 delta = Offset (
23592384 clamp (scroll_x + delta_x , 0 , self .max_scroll_x ) - scroll_x ,
23602385 clamp (scroll_y + delta_y , 0 , self .max_scroll_y ) - scroll_y ,
@@ -2365,7 +2390,7 @@ def scroll_to_region(
23652390 self .scroll_relative (
23662391 delta .x or None ,
23672392 delta .y or None ,
2368- animate = animate if ( abs ( delta_y ) > 1 or delta_x ) else False ,
2393+ animate = animate ,
23692394 speed = speed ,
23702395 duration = duration ,
23712396 easing = easing ,
@@ -2406,79 +2431,6 @@ def scroll_visible(
24062431 force = force ,
24072432 )
24082433
2409- async def _scroll_widget_to_center_of_self (
2410- self ,
2411- widget : Widget ,
2412- animate : bool = True ,
2413- * ,
2414- speed : float | None = None ,
2415- duration : float | None = None ,
2416- easing : EasingFunction | str | None = None ,
2417- force : bool = False ,
2418- origin_visible : bool = False ,
2419- ) -> None :
2420- """Scroll a widget to the center of this container. Note that this may
2421- result in more than one container scrolling, since multiple containers
2422- might be encountered on the path from `widget` to `self`.
2423-
2424- Args:
2425- widget: The widget to center.
2426- animate: Whether to animate the scroll.
2427- speed: Speed of scroll if animate is `True`; or `None` to use `duration`.
2428- duration: Duration of animation, if `animate` is `True` and `speed` is `None`.
2429- easing: An easing method for the scrolling animation.
2430- force: Force scrolling even when prohibited by overflow styling.
2431- origin_visible: Ensure that the top left corner of the widget remains visible after the scroll.
2432- """
2433-
2434- central_point = Offset (
2435- widget .virtual_region .x + (1 + widget .virtual_region .width ) // 2 ,
2436- widget .virtual_region .y + (1 + widget .virtual_region .height ) // 2 ,
2437- )
2438-
2439- container = widget .parent
2440- while isinstance (container , Widget ) and widget is not self :
2441- container_virtual_region = container .virtual_region
2442- if origin_visible and widget .region .height > container .region .height :
2443- target_region = widget .virtual_region
2444- else :
2445- # The region we want to scroll to must be centered around the central point.
2446- # We make it as big as possible because `scroll_to_region` scrolls as little
2447- # as possible.
2448- target_region = Region (
2449- central_point .x - container_virtual_region .width // 2 ,
2450- central_point .y - container_virtual_region .height // 2 ,
2451- container_virtual_region .width ,
2452- container_virtual_region .height ,
2453- )
2454-
2455- scroll = container .scroll_to_region (
2456- target_region ,
2457- animate = animate ,
2458- speed = speed ,
2459- duration = duration ,
2460- easing = easing ,
2461- force = force ,
2462- )
2463-
2464- # We scroll `widget` within `container` with the central point written in
2465- # the frame of reference of `container`. However, we need to update it so
2466- # that we are ready to scroll `container` within _its_ container.
2467- # To do this, notice that
2468- # (central_point.y - container.scroll_offset.y - scroll.y) is the number
2469- # of rows of `widget` that are visible within `container`.
2470- # We add that to `container_virtual_region.y` to find the total vertical
2471- # offset of the central point with respect to the container of `container`.
2472- # A similar calculation is made for the horizontal update.
2473- central_point = (
2474- container_virtual_region .offset
2475- + central_point
2476- - container .scroll_offset
2477- - scroll
2478- )
2479- widget = container
2480- container = widget .parent
2481-
24822434 def scroll_to_center (
24832435 self ,
24842436 widget : Widget ,
@@ -2488,7 +2440,7 @@ def scroll_to_center(
24882440 duration : float | None = None ,
24892441 easing : EasingFunction | str | None = None ,
24902442 force : bool = False ,
2491- origin_visible : bool = False ,
2443+ origin_visible : bool = True ,
24922444 ) -> None :
24932445 """Scroll this widget to the center of self.
24942446
@@ -2505,13 +2457,14 @@ def scroll_to_center(
25052457 """
25062458
25072459 self .call_after_refresh (
2508- self ._scroll_widget_to_center_of_self ,
2460+ self .scroll_to_widget ,
25092461 widget = widget ,
25102462 animate = animate ,
25112463 speed = speed ,
25122464 duration = duration ,
25132465 easing = easing ,
25142466 force = force ,
2467+ center = True ,
25152468 origin_visible = origin_visible ,
25162469 )
25172470
0 commit comments