Tools no longer have a view argument

This commit is contained in:
Arjan Molenaar 2023-12-27 15:40:36 +01:00
parent 1bfcd6be93
commit c55f260385
18 changed files with 75 additions and 97 deletions

View File

@ -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.

View File

@ -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())

View File

@ -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

View File

@ -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.

View File

@ -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):

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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``.

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -416,7 +416,6 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable):
else:
self._back_buffer = None
def update_back_buffer(self) -> None:
self.queue_draw()

View File

@ -1,5 +1,4 @@
# ruff: noqa: F402, E402
import os
import gi

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)