From c9a5d1242e4ebad6e7064d4b093c772057e659df Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Sat, 25 Jul 2015 14:00:18 +0100 Subject: [PATCH] Improvements to rect class --- wagtail/wagtailimages/rect.py | 118 +++++++++++++++++++-------- wagtail/wagtailimages/tests/tests.py | 26 +++++- 2 files changed, 111 insertions(+), 33 deletions(-) diff --git a/wagtail/wagtailimages/rect.py b/wagtail/wagtailimages/rect.py index a398df59a..04ac061e2 100644 --- a/wagtail/wagtailimages/rect.py +++ b/wagtail/wagtailimages/rect.py @@ -1,45 +1,99 @@ from __future__ import division +class Vector(object): + def __init__(self, x, y): + self.x = x + self.y = y + + def __iter__(self): + return iter((self.x, self.y)) + + def __getitem__(self, key): + return (self.x, self.y)[key] + + def __eq__(self, other): + return tuple(self) == tuple(other) + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return 'Vector(x: %d, y: %d)' % ( + self.x, self.y + ) + + class Rect(object): def __init__(self, left, top, right, bottom): - self.left = int(left) - self.top = int(top) - self.right = int(right) - self.bottom = int(bottom) + self.left = left + self.top = top + self.right = right + self.bottom = bottom + + def _get_size(self): + return Vector(self.right - self.left, self.bottom - self.top) + + def _set_size(self, new_size): + centroid = self.centroid + self.left = centroid[0] - new_size[0] / 2 + self.right = centroid[0] + new_size[0] / 2 + self.top = centroid[1] - new_size[1] / 2 + self.bottom = centroid[1] + new_size[1] / 2 + + size = property(_get_size, _set_size) + + @property + def width(self): + return self.size.x + + @property + def height(self): + return self.size.y + + def _get_centroid(self): + return Vector((self.left + self.right) / 2, (self.top + self.bottom) / 2) + + def _set_centroid(self, new_centroid): + size = self.size + self.left = new_centroid[0] - size[0] / 2 + self.right = new_centroid[0] + size[0] / 2 + self.top = new_centroid[1] - size[1] / 2 + self.bottom = new_centroid[1] + size[1] / 2 + + centroid = property(_get_centroid, _set_centroid) + + @property + def x(self): + return self.centroid.x + + @property + def y(self): + return self.centroid.y + + @property + def centroid_x(self): + # Included for backwards compatibility + return self.centroid.x + + @property + def centroid_y(self): + # Included for backwards compatibility + return self.centroid.y + + def as_tuple(self): + # No longer needed, this class should behave like a tuple + # Included for backwards compatibility + return self.left, self.top, self.right, self.bottom + + def __iter__(self): + return iter((self.left, self.top, self.right, self.bottom)) def __getitem__(self, key): return (self.left, self.top, self.right, self.bottom)[key] - @property - def width(self): - return self.right - self.left - - @property - def height(self): - return self.bottom - self.top - - @property - def size(self): - return self.width, self.height - - @property - def centroid_x(self): - return (self.left + self.right) / 2 - - @property - def centroid_y(self): - return (self.top + self.bottom) / 2 - - @property - def centroid(self): - return self.centroid_x, self.centroid_y - - def as_tuple(self): - return self.left, self.top, self.right, self.bottom - def __eq__(self, other): - return self.as_tuple() == other.as_tuple() + return tuple(self) == tuple(other) def __ne__(self, other): return not (self == other) diff --git a/wagtail/wagtailimages/tests/tests.py b/wagtail/wagtailimages/tests/tests.py index bba1e1f9c..0929d6be0 100644 --- a/wagtail/wagtailimages/tests/tests.py +++ b/wagtail/wagtailimages/tests/tests.py @@ -13,7 +13,7 @@ from wagtail.utils.deprecation import RemovedInWagtail12Warning from wagtail.tests.testapp.models import CustomImageWithAdminFormFields, CustomImageWithoutAdminFormFields from wagtail.tests.utils import WagtailTestUtils from wagtail.wagtailimages.utils import generate_signature, verify_signature -from wagtail.wagtailimages.rect import Rect +from wagtail.wagtailimages.rect import Rect, Vector from wagtail.wagtailimages.formats import Format, get_image_format, register_image_format from wagtail.wagtailimages.models import Image as WagtailImage from wagtail.wagtailimages.forms import get_image_form @@ -242,16 +242,40 @@ class TestRect(TestCase): def test_size(self): rect = Rect(100, 150, 200, 350) + self.assertIsInstance(rect.size, Vector) self.assertEqual(rect.size, (100, 200)) self.assertEqual(rect.width, 100) self.assertEqual(rect.height, 200) + def test_set_size_with_tuple(self): + rect = Rect(100, 150, 200, 350) + rect.size = (200, 400) + self.assertEqual(rect, (50, 50, 250, 450)) + + def test_set_size_with_vector(self): + rect = Rect(100, 150, 200, 350) + rect.size = Vector(200, 400) + self.assertEqual(rect, (50, 50, 250, 450)) + def test_centroid(self): rect = Rect(100, 150, 200, 350) + self.assertIsInstance(rect.centroid, Vector) self.assertEqual(rect.centroid, (150, 250)) + self.assertEqual(rect.x, 150) + self.assertEqual(rect.y, 250) self.assertEqual(rect.centroid_x, 150) self.assertEqual(rect.centroid_y, 250) + def test_set_centroid_with_tuple(self): + rect = Rect(100, 150, 200, 350) + rect.centroid = (500, 500) + self.assertEqual(rect, (450, 400, 550, 600)) + + def test_set_centroid_with_vector(self): + rect = Rect(100, 150, 200, 350) + rect.centroid = Vector(500, 500) + self.assertEqual(rect, (450, 400, 550, 600)) + def test_repr(self): rect = Rect(100, 150, 200, 250) self.assertEqual(repr(rect), "Rect(left: 100, top: 150, right: 200, bottom: 250)")