From c55f260385178f31f9cead48b18145788c86b648 Mon Sep 17 00:00:00 2001 From: Arjan Molenaar Date: Wed, 27 Dec 2023 15:40:36 +0100 Subject: [PATCH] Tools no longer have a view argument --- docs/guide.rst | 4 ++-- docs/segment.rst | 4 ++-- examples/demo.py | 27 ++++++++++++-------------- examples/exampleitems.py | 1 + examples/simple-box.py | 8 ++++---- gaphas/tool/hover.py | 3 +-- gaphas/tool/itemtool.py | 2 +- gaphas/tool/placement.py | 5 +---- gaphas/tool/rubberband.py | 2 +- gaphas/tool/scroll.py | 13 ++++++------- gaphas/tool/viewfocus.py | 2 +- gaphas/tool/zoom.py | 37 ++++++++++++++++++------------------ gaphas/view/gtkview.py | 1 - tests/conftest.py | 1 - tests/test_tool_hover.py | 34 +++++++++------------------------ tests/test_tool_item.py | 4 ++-- tests/test_tool_placement.py | 6 +++--- tests/test_tool_zoom.py | 18 ++++++++++-------- 18 files changed, 75 insertions(+), 97 deletions(-) diff --git a/docs/guide.rst b/docs/guide.rst index 1236034..7666e6b 100644 --- a/docs/guide.rst +++ b/docs/guide.rst @@ -19,7 +19,7 @@ Guides consist of a couple of elements: aspects that hook into the item-drag cyc ... .append(HandlePainter(view)) ... .append(GuidePainter(view)) ... ) - >>> view.add_controller(item_tool(view)) - >>> view.add_controller(zoom_tool(view)) + >>> view.add_controller(item_tool()) + >>> view.add_controller(zoom_tool()) You need to hook up the ``GuidePainter``. The aspect are loaded as soon as the module is loaded. diff --git a/docs/segment.rst b/docs/segment.rst index 6130b7d..70107dd 100644 --- a/docs/segment.rst +++ b/docs/segment.rst @@ -21,5 +21,5 @@ to actually use it, the ``segment`` module needs to be imported. ... .append(HandlePainter(view)) ... .append(LineSegmentPainter(view.selection)) ... ) - >>> view.add_controller(item_tool(view)) - >>> view.add_controller(zoom_tool(view)) + >>> view.add_controller(item_tool()) + >>> view.add_controller(zoom_tool()) diff --git a/examples/demo.py b/examples/demo.py index 7670c95..9415456 100755 --- a/examples/demo.py +++ b/examples/demo.py @@ -137,6 +137,7 @@ def text_underline(cr, x, y, text, offset=1.5): cr.rel_line_to(x_adv, 0) cr.stroke() + def rubberband_state(view): try: return view.rubberband_state @@ -147,14 +148,14 @@ def rubberband_state(view): def apply_default_tool_set(view): view.remove_all_controllers() - view.add_controller(item_tool(view)) - for tool in zoom_tools(view): + view.add_controller(item_tool()) + for tool in zoom_tools(): view.add_controller(tool) - view.add_controller(pan_tool(view)) - view.add_controller(view_focus_tool(view)) + view.add_controller(pan_tool()) + view.add_controller(view_focus_tool()) - view.add_controller(rubberband_tool(view, rubberband_state(view))) - view.add_controller(hover_tool(view)) + view.add_controller(rubberband_tool(rubberband_state(view))) + view.add_controller(hover_tool()) return rubberband_state @@ -163,12 +164,12 @@ def apply_placement_tool_set(view, item_type, handle_index): apply_default_tool_set(view) view.remove_all_controllers() - tool = placement_tool(view, factory(view, item_type), handle_index) + tool = placement_tool(factory(view, item_type), handle_index) tool.connect("drag-end", unset_placement_tool) - for tool in zoom_tools(view): - view.add_controller(tool) - view.add_controller(view_focus_tool(view)) view.add_controller(tool) + for tool in zoom_tools(): + view.add_controller(tool) + view.add_controller(view_focus_tool()) def apply_painters(view): @@ -283,9 +284,7 @@ def create_window(canvas, title, zoom=1.0): # noqa too complex assert view.model painter = ItemPainter() - bounding_box = calculate_bounding_box( - painter, canvas.get_all_items() - ) + bounding_box = calculate_bounding_box(painter, canvas.get_all_items()) surface = cairo.ImageSurface( cairo.FORMAT_ARGB32, int(bounding_box.width), int(bounding_box.height) @@ -422,8 +421,6 @@ def main(): if __name__ == "__main__": - import sys - if "-p" in sys.argv: print("Profiling...") import hotshot diff --git a/examples/exampleitems.py b/examples/exampleitems.py index 95adca2..df25723 100644 --- a/examples/exampleitems.py +++ b/examples/exampleitems.py @@ -143,6 +143,7 @@ def text_multiline(cr, x, y, text): cr.move_to(x, y) cr.show_text(line) + def path_ellipse(cr, x, y, width, height, angle=0): """Draw an ellipse. diff --git a/examples/simple-box.py b/examples/simple-box.py index 54c8c84..07a1fcd 100755 --- a/examples/simple-box.py +++ b/examples/simple-box.py @@ -16,10 +16,10 @@ from examples.exampleitems import Box def apply_default_tool_set(view): view.remove_all_controllers() - view.add_controller(item_tool(view)) - view.add_controller(zoom_tool(view)) - view.add_controller(view_focus_tool(view)) - view.add_controller(hover_tool(view)) + view.add_controller(item_tool()) + view.add_controller(zoom_tool()) + view.add_controller(view_focus_tool()) + view.add_controller(hover_tool()) def create_canvas(canvas, title): diff --git a/gaphas/tool/hover.py b/gaphas/tool/hover.py index e4aee99..10af7a2 100644 --- a/gaphas/tool/hover.py +++ b/gaphas/tool/hover.py @@ -2,10 +2,9 @@ from gi.repository import Gdk, Gtk from gaphas.cursor import cursor from gaphas.tool.itemtool import find_item_and_handle_at_point -from gaphas.view import GtkView -def hover_tool(view: GtkView) -> Gtk.EventController: +def hover_tool() -> Gtk.EventController: """Highlight the currently hovered item.""" ctrl = Gtk.EventControllerMotion.new() ctrl.connect("motion", on_motion) diff --git a/gaphas/tool/itemtool.py b/gaphas/tool/itemtool.py index 754f585..9b33ffe 100644 --- a/gaphas/tool/itemtool.py +++ b/gaphas/tool/itemtool.py @@ -16,7 +16,7 @@ from gaphas.view import GtkView log = logging.getLogger(__name__) -def item_tool(view: GtkView) -> Gtk.GestureDrag: +def item_tool() -> Gtk.GestureDrag: """Handle item movement and movement of handles.""" gesture = Gtk.GestureDrag.new() drag_state = DragState() diff --git a/gaphas/tool/placement.py b/gaphas/tool/placement.py index c81764c..1d1a321 100644 --- a/gaphas/tool/placement.py +++ b/gaphas/tool/placement.py @@ -5,14 +5,11 @@ from gi.repository import Gtk from gaphas.handlemove import HandleMove from gaphas.item import Item from gaphas.move import MoveType -from gaphas.view import GtkView FactoryType = Callable[[], Item] -def placement_tool( - view: GtkView, factory: FactoryType, handle_index: int -) -> Gtk.GestureDrag: +def placement_tool(factory: FactoryType, handle_index: int) -> Gtk.GestureDrag: """Place a new item on the model.""" gesture = Gtk.GestureDrag.new() placement_state = PlacementState(factory, handle_index) diff --git a/gaphas/tool/rubberband.py b/gaphas/tool/rubberband.py index b77665c..04b9283 100644 --- a/gaphas/tool/rubberband.py +++ b/gaphas/tool/rubberband.py @@ -38,7 +38,7 @@ class RubberbandPainter: cairo.stroke() -def rubberband_tool(view, rubberband_state): +def rubberband_tool(rubberband_state): """Rubberband selection tool. Should be used in conjunction with ``RubberbandPainter``. diff --git a/gaphas/tool/scroll.py b/gaphas/tool/scroll.py index cc1f4fa..7e2f5db 100644 --- a/gaphas/tool/scroll.py +++ b/gaphas/tool/scroll.py @@ -2,14 +2,13 @@ from gi.repository import Gdk, Gtk from gaphas.tool.zoom import Zoom from gaphas.tool.hover import set_cursor -from gaphas.view import GtkView -def scroll_tools(view: GtkView, speed: int = 10) -> Gtk.EventControllerScroll: - return scroll_tool(view, speed), pan_tool(view) +def scroll_tools(speed: int = 10) -> Gtk.EventControllerScroll: + return scroll_tool(speed), pan_tool() -def scroll_tool(view: GtkView, speed: int = 10) -> Gtk.EventControllerScroll: +def scroll_tool(speed: int = 10) -> Gtk.EventControllerScroll: """Scroll tool recognized 2 finger scroll gestures.""" ctrl = Gtk.EventControllerScroll.new(Gtk.EventControllerScrollFlags.BOTH_AXES) ctrl.connect("scroll", on_scroll, speed) @@ -26,8 +25,8 @@ def on_scroll(controller, dx, dy, speed): view = controller.get_widget() x = view.get_width() / 2 y = view.get_height() / 2 - zoom = Zoom(view.matrix) - zoom.begin(x, y) + zoom = Zoom() + zoom.begin(view.matrix, x, y) zoom_factor = 0.1 d = 1 - dy * zoom_factor @@ -49,7 +48,7 @@ class PanState: self.v = 0 -def pan_tool(view: GtkView) -> Gtk.GestureDrag: +def pan_tool() -> Gtk.GestureDrag: gesture = Gtk.GestureDrag.new() gesture.set_button(Gdk.BUTTON_MIDDLE) pan_state = PanState() diff --git a/gaphas/tool/viewfocus.py b/gaphas/tool/viewfocus.py index ae30fac..826cda9 100644 --- a/gaphas/tool/viewfocus.py +++ b/gaphas/tool/viewfocus.py @@ -1,7 +1,7 @@ from gi.repository import Gtk -def view_focus_tool(view): +def view_focus_tool(): """This little tool ensures the view grabs focus when a mouse press or touch event happens.""" gesture = Gtk.GestureSingle() diff --git a/gaphas/tool/zoom.py b/gaphas/tool/zoom.py index eab83f7..c902245 100644 --- a/gaphas/tool/zoom.py +++ b/gaphas/tool/zoom.py @@ -2,24 +2,24 @@ from __future__ import annotations from gi.repository import Gdk, Gtk -from gaphas.view import GtkView - class Zoom: - def __init__(self, matrix): - self.matrix = matrix + def __init__(self): + self.matrix = None self.x0 = 0 self.y0 = 0 self.sx = 1.0 self.sy = 1.0 - def begin(self, x0, y0): + def begin(self, matrix, x0, y0): + self.matrix = matrix self.x0 = x0 self.y0 = y0 - self.sx = self.matrix[0] - self.sy = self.matrix[3] + self.sx = matrix[0] + self.sy = matrix[3] def update(self, scale): + assert self.matrix if self.sx * scale < 0.2: scale = 0.2 / self.sx elif self.sx * scale > 20.0: @@ -37,18 +37,18 @@ class Zoom: m.translate(+ox, +oy) -def zoom_tools( - view: GtkView, -) -> tuple[Gtk.GestureZoom] | tuple[Gtk.GestureZoom, Gtk.EventControllerScroll]: - return (zoom_tool(view), scroll_zoom_tool(view)) +def zoom_tools() -> ( + tuple[Gtk.GestureZoom] | tuple[Gtk.GestureZoom, Gtk.EventControllerScroll] +): + return zoom_tool(), scroll_zoom_tool() -def zoom_tool(view: GtkView) -> Gtk.GestureZoom: +def zoom_tool() -> Gtk.GestureZoom: """Create a zoom tool as a Gtk.Gesture. Note: we need to keep a reference to this gesture, or else it will be destroyed. """ - zoom = Zoom(view.matrix) + zoom = Zoom() gesture = Gtk.GestureZoom.new() gesture.set_propagation_phase(Gtk.PropagationPhase.CAPTURE) gesture.connect("begin", on_begin, zoom) @@ -61,15 +61,16 @@ def on_begin( sequence: None, zoom: Zoom, ) -> None: + view = gesture.get_widget() _, x0, y0 = gesture.get_point(sequence) - zoom.begin(x0, y0) + zoom.begin(view.matrix, x0, y0) -def on_scale_changed(gesture: Gtk.GestureZoom, scale: float, zoom: Zoom) -> None: +def on_scale_changed(_gesture: Gtk.GestureZoom, scale: float, zoom: Zoom) -> None: zoom.update(scale) -def scroll_zoom_tool(view: GtkView) -> Gtk.EventControllerScroll: +def scroll_zoom_tool() -> Gtk.EventControllerScroll: """Ctrl-scroll wheel zoom. GTK4 only. @@ -91,8 +92,8 @@ def on_scroll(controller, _dx, dy): view = controller.get_widget() x = view.get_width() / 2 y = view.get_height() / 2 - zoom = Zoom(view.matrix) - zoom.begin(x, y) + zoom = Zoom() + zoom.begin(view.matrix, x, y) zoom_factor = 0.1 d = 1 - dy * zoom_factor diff --git a/gaphas/view/gtkview.py b/gaphas/view/gtkview.py index 174228e..65f9388 100644 --- a/gaphas/view/gtkview.py +++ b/gaphas/view/gtkview.py @@ -416,7 +416,6 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable): else: self._back_buffer = None - def update_back_buffer(self) -> None: self.queue_draw() diff --git a/tests/conftest.py b/tests/conftest.py index 6d80b22..1aa1985 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,4 @@ # ruff: noqa: F402, E402 -import os import gi diff --git a/tests/test_tool_hover.py b/tests/test_tool_hover.py index e977bd6..dc9cd43 100644 --- a/tests/test_tool_hover.py +++ b/tests/test_tool_hover.py @@ -1,35 +1,19 @@ -import pytest -from gi.repository import Gdk, Gtk - -from gaphas.tool.hover import hover_tool - -GTK4 = Gtk._version == "4.0" +from gaphas.tool.hover import hover_tool, on_motion -@pytest.fixture -def motion_event(): - event = Gdk.Event() - event.type = Gdk.EventType.MOTION_NOTIFY - return event +def test_hovers_item(view, box): + tool = hover_tool() + view.add_controller(tool) - -@pytest.mark.skipif(GTK4, reason="test does work on GTK 3 only") -def test_hovers_item(view, box, motion_event): - tool = hover_tool(view) - motion_event.x = 5 - motion_event.y = 5 - - tool.handle_event(motion_event) + on_motion(tool, 5, 5) assert view.selection.hovered_item is box -@pytest.mark.skipif(GTK4, reason="test does work on GTK 3 only") -def test_handles_event(view, box, motion_event): - tool = hover_tool(view) - motion_event.x = 100 - motion_event.y = 100 +def test_handles_event(view, box): + tool = hover_tool() + view.add_controller(tool) - tool.handle_event(motion_event) + on_motion(tool, 100, 100) assert view.selection.hovered_item is None diff --git a/tests/test_tool_item.py b/tests/test_tool_item.py index 10c9dc7..60453be 100644 --- a/tests/test_tool_item.py +++ b/tests/test_tool_item.py @@ -41,8 +41,8 @@ class MockGesture: pass -def test_should_create_a_gesture(view): - tool = item_tool(view) +def test_should_create_a_gesture(): + tool = item_tool() assert isinstance(tool, Gtk.Gesture) diff --git a/tests/test_tool_placement.py b/tests/test_tool_placement.py index eacf3d9..522fbf5 100644 --- a/tests/test_tool_placement.py +++ b/tests/test_tool_placement.py @@ -13,15 +13,15 @@ def tool_factory(connections): return tool_factory -def test_can_create_placement_tool(view, tool_factory): - tool = placement_tool(view, tool_factory, 2) +def test_can_create_placement_tool(tool_factory): + tool = placement_tool(tool_factory, 2) assert isinstance(tool, Gtk.Gesture) def test_create_new_element(view, tool_factory, window): state = PlacementState(tool_factory, 2) - tool = placement_tool(view, tool_factory, 2) + tool = placement_tool(tool_factory, 2) view.add_controller(tool) on_drag_begin(tool, 0, 0, state) diff --git a/tests/test_tool_zoom.py b/tests/test_tool_zoom.py index e665f8f..638d744 100644 --- a/tests/test_tool_zoom.py +++ b/tests/test_tool_zoom.py @@ -6,16 +6,17 @@ from gaphas.tool.zoom import Zoom, on_begin, on_scale_changed, zoom_tool @pytest.fixture def zoom_data(view): - zoom_data = Zoom(view.matrix) + zoom_data = Zoom() zoom_data.x0 = 0 zoom_data.y0 = 0 zoom_data.sx = 1 zoom_data.sy = 1 + zoom_data.begin(view.matrix, 0, 0) return zoom_data def test_can_create_zoom_tool(view): - tool = zoom_tool(view) + tool = zoom_tool() view.add_controller(tool) assert isinstance(tool, Gtk.Gesture) @@ -41,7 +42,7 @@ def test_begin_state(zoom_data, view): def test_scaling(zoom_data, view): - tool = zoom_tool(view) + tool = zoom_tool() view.add_controller(tool) on_scale_changed(tool, 1.2, zoom_data) @@ -51,7 +52,7 @@ def test_scaling(zoom_data, view): def test_multiple_scaling_events(zoom_data, view): - tool = zoom_tool(view) + tool = zoom_tool() view.add_controller(tool) on_scale_changed(tool, 1.1, zoom_data) @@ -62,7 +63,7 @@ def test_multiple_scaling_events(zoom_data, view): def test_scaling_with_unequal_scaling_factor(zoom_data, view): - tool = zoom_tool(view) + tool = zoom_tool() view.add_controller(tool) zoom_data.sx = 2 @@ -74,7 +75,7 @@ def test_scaling_with_unequal_scaling_factor(zoom_data, view): def test_zoom_should_center_around_mouse_cursor(zoom_data, view): - tool = zoom_tool(view) + tool = zoom_tool() view.add_controller(tool) zoom_data.x0 = 100 zoom_data.y0 = 50 @@ -86,8 +87,9 @@ def test_zoom_should_center_around_mouse_cursor(zoom_data, view): def test_zoom_out_should_be_limited_to_20_percent(zoom_data, view): - tool = zoom_tool(view) + tool = zoom_tool() view.add_controller(tool) + on_scale_changed(tool, 0.0, zoom_data) assert view.matrix[0] == pytest.approx(0.2) @@ -95,7 +97,7 @@ def test_zoom_out_should_be_limited_to_20_percent(zoom_data, view): def test_zoom_in_should_be_limited_to_20_times(zoom_data, view): - tool = zoom_tool(view) + tool = zoom_tool() view.add_controller(tool) on_scale_changed(tool, 100.0, zoom_data)