From 923a72fef676c34e9cb48a295e837a2e52893fad Mon Sep 17 00:00:00 2001 From: Andrew Hamilton Date: Mon, 24 Jan 2022 23:06:42 +1000 Subject: [PATCH] fill3: Optionally limit scroll of portals --- fill3/fill3/__init__.py | 26 +++++++++++++++++++++++++- fill3/tests/fill3_test.py | 9 +++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/fill3/fill3/__init__.py b/fill3/fill3/__init__.py index f7d166a..ef8bbc7 100755 --- a/fill3/fill3/__init__.py +++ b/fill3/fill3/__init__.py @@ -202,10 +202,14 @@ class ScrollBar: class Portal: - def __init__(self, widget, position=(0, 0), background_char=" "): + def __init__(self, widget, position=(0, 0), background_char=" ", + is_scroll_limited=False, is_left_aligned=True, is_top_aligned=True): self.widget = widget self.position = position self.background_char = background_char + self.is_scroll_limited = is_scroll_limited + self.is_left_aligned = is_left_aligned + self.is_top_aligned = is_top_aligned self.last_dimensions = 0, 0 def _scroll_half_pages(self, dx, dy): @@ -225,6 +229,24 @@ class Portal: def scroll_right(self): self._scroll_half_pages(1, 0) + def limit_scroll(self, portal_dimensions, appearance_dimensions): + portal_width, portal_height = portal_dimensions + widget_width, widget_height = appearance_dimensions + x, y = self.position + if widget_width <= portal_width: + x = 0 if self.is_left_aligned else (widget_width - portal_width) + elif x < 0: + x = 0 + elif x > (widget_width - portal_width): + x = widget_width - portal_width + if widget_height <= portal_height: + y = 0 if self.is_top_aligned else (widget_height - portal_height) + elif y < 0: + y = 0 + elif y > (widget_height - portal_height): + y = widget_height - portal_height + return x, y + def appearance_for(self, dimensions): width, height = dimensions x, y = self.position @@ -232,6 +254,8 @@ class Portal: appearance = self.widget.appearance_interval((max(y, 0), y+height)) except AttributeError: appearance = self.widget.appearance()[max(y, 0):y+height] + if self.is_scroll_limited: + x, y = self.limit_scroll(dimensions, appearance_dimensions(appearance)) self.last_dimensions = dimensions top = [self.background_char * width] * -y if y < 0 else [] bottom = appearance_resize([row[max(x, 0):x+width] for row in appearance], diff --git a/fill3/tests/fill3_test.py b/fill3/tests/fill3_test.py index b2b007c..a9139a5 100755 --- a/fill3/tests/fill3_test.py +++ b/fill3/tests/fill3_test.py @@ -45,6 +45,15 @@ class WidgetTests(unittest.TestCase): self.assert_string(portal.appearance_for((8, 3)), " \n foobar \n ") portal.position = (5, 0) self.assert_string(portal.appearance_for((2, 1)), "r ") + # limit scroll + portal.position = (0, 0) + self.assertEqual(portal.limit_scroll((1, 1), (1, 1)), (0, 0)) + portal.position = (-1, 0) + self.assertEqual(portal.limit_scroll((1, 1), (1, 1)), (0, 0)) + portal.position = (1, 0) + self.assertEqual(portal.limit_scroll((6, 1), (1, 1)), (0, 0)) + portal.is_left_aligned = False + self.assertEqual(portal.limit_scroll((6, 1), (1, 1)), (-5, 0)) def test_border_widget(self): contents = fill3.Filler(self.TEXT_A)