Add snapping for rotating

This commit is contained in:
Rebecca Breu 2021-04-06 16:19:02 +02:00
parent be9adfdf4c
commit 55819bf4c4
4 changed files with 42 additions and 5 deletions

View file

@ -315,9 +315,17 @@ class SelectableMixin(BaseItemMixin):
diff = pos - self.event_anchor
return -math.degrees(math.atan2(diff.x(), diff.y()))
def get_rotate_delta(self, pos):
"""Get the rotate delta for the current mouse movement"""
return self.get_rotate_angle(pos) - self.rotate_start_angle
def get_rotate_delta(self, pos, snap=False):
"""Get the rotate delta for the current mouse movement.
If ``snap`` is True, snap to 15 degree units."""
delta = self.get_rotate_angle(pos) - self.rotate_start_angle
if snap:
target = utils.round_to(self.rotate_orig_degrees + delta, 15)
delta = target - self.rotate_orig_degrees
return delta
def mouseMoveEvent(self, event):
if self.scale_active:
@ -327,7 +335,9 @@ class SelectableMixin(BaseItemMixin):
item.mapFromScene(self.event_anchor))
event.accept()
elif self.rotate_active:
delta = self.get_rotate_delta(event.scenePos())
snap = (event.modifiers() == Qt.KeyboardModifiers.ControlModifier
or event.modifiers() == Qt.KeyboardModifiers.ShiftModifier)
delta = self.get_rotate_delta(event.scenePos(), snap)
for item in self.selection_action_items():
item.setRotation(item.rotate_orig_degrees + delta,
item.mapFromScene(self.event_anchor))

View file

@ -28,3 +28,12 @@ def get_rect_from_points(point1, point2):
max(point1.x(), point2.x()),
max(point1.y(), point2.y()))
return QtCore.QRectF(topleft, bottomright)
def round_to(number, base):
"""Rounds to the given base.
E.g. with ``base=5`` round to the nearest number divisible by 5.
"""
return base * round(number / base)

View file

@ -344,7 +344,7 @@ class SelectableMixinTestCase(SelectableMixinBaseTestCase):
assert shape.bottomRight().y() == 80
class SelectableMixinScalingTestCase(SelectableMixinBaseTestCase):
class SelectableMixinCalculationsTestCase(SelectableMixinBaseTestCase):
def test_get_scale_factor_bottomright(self):
self.item.event_start = QtCore.QPointF(10, 10)
@ -423,6 +423,13 @@ class SelectableMixinScalingTestCase(SelectableMixinBaseTestCase):
self.item.rotate_start_angle = -3
assert self.item.get_rotate_delta(QtCore.QPointF(15, 25)) == -42
def test_get_rotate_delta_snaps(self):
self.item.event_anchor = QtCore.QPointF(10, 20)
self.item.rotate_start_angle = -3
self.item.rotate_orig_degrees = 5
assert self.item.get_rotate_delta(
QtCore.QPointF(15, 25), snap=True) == -35
class SelectableMixinMouseEventsTestCase(SelectableMixinBaseTestCase):

View file

@ -1,3 +1,5 @@
import pytest
from PyQt6 import QtCore
from beeref import utils
@ -21,3 +23,12 @@ class GetRectFromPointsTestCase(BeeTestCase):
assert rect.topLeft().y() == -20
assert rect.bottomRight().x() == 50
assert rect.bottomRight().y() == 40
@pytest.mark.parametrize('number,base,expected',
[(33, 5, 35),
(-33, 5, -35),
(50, 5, 50),
(3.1, 0.5, 3.0)])
def test_round_to(number, base, expected):
assert utils.round_to(number, base) == expected