From c81a5aa4dcaac20b0f31ab4f6ffe1933ec9e472a Mon Sep 17 00:00:00 2001 From: edward-jazzhands Date: Tue, 12 Nov 2024 01:37:23 -0400 Subject: [PATCH 1/7] Modified viewer.py to add 3 arguments to the class: min_zoom: int, max_zoom: int, and nested: bool. --- textual_imageview/viewer.py | 65 ++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/textual_imageview/viewer.py b/textual_imageview/viewer.py index 4f635c3..aa99036 100644 --- a/textual_imageview/viewer.py +++ b/textual_imageview/viewer.py @@ -16,7 +16,23 @@ class ImageViewer(Widget): } """ - def __init__(self, image: Image.Image): + def __init__( + self, + image: Image.Image, + min_zoom: int = 10, + max_zoom: int = 1, + nested: bool = False, + ): + """A widget that displays an image and allows zooming and panning. + + Args: + image (Image.Image): The image to display. + min_zoom (int, optional): The minimum zoom level. Defaults to 10. + max_zoom (int, optional): The maximum zoom level. Defaults to 0. + nested (bool, optional): Whether the ImageViewer will be a child inside another Widget. Defaults to False. + + Setting `nested` to True will make the ImageViewer only respond to mouse events when it has focus. """ + super().__init__() if not isinstance(image, Image.Image): raise TypeError( @@ -25,6 +41,9 @@ def __init__(self, image: Image.Image): self.image = ImageView(image) self.mouse_down = False + self.min_zoom = min_zoom + self.max_zoom = max_zoom + self.nested = nested def on_show(self): w, h = self.size.width, self.size.height @@ -44,18 +63,42 @@ def on_show(self): self.refresh() def on_mouse_scroll_down(self, event: events.MouseScrollDown): - offset = self.region.offset - zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) - self.image.zoom(1, zoom_position) - self.refresh() - event.stop() + """scroll down to zoom out""" + + func_pass = False + if self.parent.has_focus or not self.nested: + func_pass = True + + if func_pass: + + offset = self.region.offset + zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) + zoom_level = self.image._zoom + + if zoom_level < self.min_zoom: + self.image.zoom(1, zoom_position) + + self.refresh() + event.stop() def on_mouse_scroll_up(self, event: events.MouseScrollDown): - offset = self.region.offset - zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) - self.image.zoom(-1, zoom_position) - self.refresh() - event.stop() + """scroll up to zoom in""" + + func_pass = False + if self.parent.has_focus or not self.nested: + func_pass = True + + if func_pass: + + offset = self.region.offset + zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) + zoom_level = self.image._zoom + + if zoom_level > self.max_zoom: + self.image.zoom(-1, zoom_position) + + self.refresh() + event.stop() def on_mouse_down(self, _: events.MouseDown): self.mouse_down = True From 796b5afb2b866ce843577248a16ea736f98a3a91 Mon Sep 17 00:00:00 2001 From: edward-jazzhands Date: Tue, 12 Nov 2024 03:07:56 -0400 Subject: [PATCH 2/7] fixed new docstring --- textual_imageview/viewer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/textual_imageview/viewer.py b/textual_imageview/viewer.py index aa99036..16a2112 100644 --- a/textual_imageview/viewer.py +++ b/textual_imageview/viewer.py @@ -28,10 +28,11 @@ def __init__( Args: image (Image.Image): The image to display. min_zoom (int, optional): The minimum zoom level. Defaults to 10. - max_zoom (int, optional): The maximum zoom level. Defaults to 0. + max_zoom (int, optional): The maximum zoom level. Defaults to 1. nested (bool, optional): Whether the ImageViewer will be a child inside another Widget. Defaults to False. - Setting `nested` to True will make the ImageViewer only respond to mouse events when it has focus. """ + Setting `nested` to True will make the ImageViewer only capture the mouse scroll up/down when it has focus. + (This is useful if it is inside a scrollable container) """ super().__init__() if not isinstance(image, Image.Image): From 0dddb55f50e29b12d1038b8fb0923cfbf3a9a0d3 Mon Sep 17 00:00:00 2001 From: edward-jazzhands Date: Tue, 12 Nov 2024 03:21:24 -0400 Subject: [PATCH 3/7] fixed new docstring --- textual_imageview/viewer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/textual_imageview/viewer.py b/textual_imageview/viewer.py index 16a2112..dad1cff 100644 --- a/textual_imageview/viewer.py +++ b/textual_imageview/viewer.py @@ -22,6 +22,7 @@ def __init__( min_zoom: int = 10, max_zoom: int = 1, nested: bool = False, + id: str | None = None, ): """A widget that displays an image and allows zooming and panning. @@ -30,11 +31,14 @@ def __init__( min_zoom (int, optional): The minimum zoom level. Defaults to 10. max_zoom (int, optional): The maximum zoom level. Defaults to 1. nested (bool, optional): Whether the ImageViewer will be a child inside another Widget. Defaults to False. + id: The ID of the widget in the DOM. Setting `nested` to True will make the ImageViewer only capture the mouse scroll up/down when it has focus. - (This is useful if it is inside a scrollable container) """ + (This is useful if it is inside a scrollable container) - super().__init__() + Note: passing through *args and **kwargs to Widget class is blocked except for the `id` parameter.""" + + super().__init__(id=id) if not isinstance(image, Image.Image): raise TypeError( f"Expected PIL Image, but received '{type(image).__name__}' instead." From 920d273380747061c37bf0751ed4801de0690a78 Mon Sep 17 00:00:00 2001 From: edward-jazzhands Date: Tue, 12 Nov 2024 03:33:31 -0400 Subject: [PATCH 4/7] added log.events for zoom in and zoom out --- textual_imageview/viewer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/textual_imageview/viewer.py b/textual_imageview/viewer.py index dad1cff..c31ad66 100644 --- a/textual_imageview/viewer.py +++ b/textual_imageview/viewer.py @@ -79,6 +79,7 @@ def on_mouse_scroll_down(self, event: events.MouseScrollDown): offset = self.region.offset zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) zoom_level = self.image._zoom + self.log.event(f"Zoom level: {zoom_level}") if zoom_level < self.min_zoom: self.image.zoom(1, zoom_position) @@ -98,6 +99,7 @@ def on_mouse_scroll_up(self, event: events.MouseScrollDown): offset = self.region.offset zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) zoom_level = self.image._zoom + self.log.event(f"Zoom level: {zoom_level}") if zoom_level > self.max_zoom: self.image.zoom(-1, zoom_position) From 6a3255202a0729af1aa291bd01ea345577cd0dd4 Mon Sep 17 00:00:00 2001 From: edward-jazzhands Date: Tue, 12 Nov 2024 04:44:31 -0400 Subject: [PATCH 5/7] Improved wording in docstring --- textual_imageview/viewer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/textual_imageview/viewer.py b/textual_imageview/viewer.py index c31ad66..094c233 100644 --- a/textual_imageview/viewer.py +++ b/textual_imageview/viewer.py @@ -33,8 +33,8 @@ def __init__( nested (bool, optional): Whether the ImageViewer will be a child inside another Widget. Defaults to False. id: The ID of the widget in the DOM. - Setting `nested` to True will make the ImageViewer only capture the mouse scroll up/down when it has focus. - (This is useful if it is inside a scrollable container) + Setting `nested` to True will make the ImageViewer only capture the mouse scroll up/down when its parent has focus. + This is useful when it's a child of another Widget, or you just want to control when it's allowed to zoom. Note: passing through *args and **kwargs to Widget class is blocked except for the `id` parameter.""" From 45ee937bdef6fa1a8844a938ff0b3e78cccd25de Mon Sep 17 00:00:00 2001 From: edward-jazzhands Date: Tue, 12 Nov 2024 04:59:32 -0400 Subject: [PATCH 6/7] removed redundant lines --- textual_imageview/viewer.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/textual_imageview/viewer.py b/textual_imageview/viewer.py index 094c233..48e2507 100644 --- a/textual_imageview/viewer.py +++ b/textual_imageview/viewer.py @@ -70,11 +70,7 @@ def on_show(self): def on_mouse_scroll_down(self, event: events.MouseScrollDown): """scroll down to zoom out""" - func_pass = False if self.parent.has_focus or not self.nested: - func_pass = True - - if func_pass: offset = self.region.offset zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) @@ -90,11 +86,7 @@ def on_mouse_scroll_down(self, event: events.MouseScrollDown): def on_mouse_scroll_up(self, event: events.MouseScrollDown): """scroll up to zoom in""" - func_pass = False if self.parent.has_focus or not self.nested: - func_pass = True - - if func_pass: offset = self.region.offset zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) From e2c3c81d896da711582b0c1f97f99b4b5261b2c4 Mon Sep 17 00:00:00 2001 From: edward-jazzhands Date: Thu, 14 Nov 2024 21:19:54 -0400 Subject: [PATCH 7/7] moved new log statements to the correct spot --- textual_imageview/viewer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/textual_imageview/viewer.py b/textual_imageview/viewer.py index 48e2507..4facc1e 100644 --- a/textual_imageview/viewer.py +++ b/textual_imageview/viewer.py @@ -75,11 +75,12 @@ def on_mouse_scroll_down(self, event: events.MouseScrollDown): offset = self.region.offset zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) zoom_level = self.image._zoom - self.log.event(f"Zoom level: {zoom_level}") if zoom_level < self.min_zoom: self.image.zoom(1, zoom_position) + self.log.event(f"Zoom level: {zoom_level}") + self.refresh() event.stop() @@ -91,11 +92,12 @@ def on_mouse_scroll_up(self, event: events.MouseScrollDown): offset = self.region.offset zoom_position = self.image.rowcol_to_xy(event.y, event.x, (offset.y, offset.x)) zoom_level = self.image._zoom - self.log.event(f"Zoom level: {zoom_level}") if zoom_level > self.max_zoom: self.image.zoom(-1, zoom_position) + self.log.event(f"Zoom level: {zoom_level}") + self.refresh() event.stop()