def test_init_srcUdst_translated(self): src = Rectangle([100, 100, 300, 200]) dst = Rectangle([10, 10, 200, 100]) tobj = DrawingContext(src, dst) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(15.0, 10.0), tobj.t_translate()) self.assertEqual(0.9, tobj.scale()) src = Rectangle([100, 100, 300, 200]) dst = Rectangle([10, 10, 200, 100]) tobj = DrawingContext(src, dst, border=0.25) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(60.0, 32.5), tobj.t_translate()) self.assertEqual(0.45, tobj.scale()) src = Rectangle([100, 100, 300, 200]) dst = Rectangle([10, 10, 2000, 1000]) tobj = DrawingContext(src, dst, border=0) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(15.0, 10.0), tobj.t_translate()) self.assertEqual(9.9, tobj.scale()) src = Rectangle([100, 100, 300, 200]) dst = Rectangle([10, 10, 2000, 1000]) tobj = DrawingContext(src, dst, border=0.25) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(510.0, 257.5), tobj.t_translate()) self.assertEqual(4.95, tobj.scale()) src = Rectangle([100, 100, 300, 200]) dst = Rectangle([10, 10, 2000, 100]) tobj = DrawingContext(src, dst, border=0.25) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(960.0, 32.5), tobj.t_translate()) self.assertEqual(0.45, tobj.scale())
def test_init_src_translated(self): src = Rectangle([100, 100, 300, 200]) dst = Rectangle([0, 0, 200, 100]) tobj = DrawingContext(src, dst) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(0, 0), tobj.t_translate()) self.assertEqual(1, tobj.scale()) src = Rectangle([100, 100, 300, 200]) dst = Rectangle([0, 0, 200, 100]) tobj = DrawingContext(src, dst, border=0.25) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(50, 25), tobj.t_translate()) self.assertEqual(0.5, tobj.scale()) src = Rectangle([100, 100, 300, 200]) dst = Rectangle([0, 0, 2000, 1000]) tobj = DrawingContext(src, dst, border=0) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(0, 0), tobj.t_translate()) self.assertEqual(10, tobj.scale()) src = Rectangle([100, 100, 300, 200]) dst = Rectangle([0, 0, 2000, 1000]) tobj = DrawingContext(src, dst, border=0.25) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(500.0, 250.0), tobj.t_translate()) self.assertEqual(5, tobj.scale()) src = Rectangle([100, 100, 300, 200]) dst = Rectangle([0, 0, 2000, 100]) tobj = DrawingContext(src, dst, border=0.25) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(950.0, 25.0), tobj.t_translate()) self.assertEqual(0.5, tobj.scale())
def test_eq(self): s = Point(3, 9) e = Point(5, 1) tobj = Rectangle(s, e) self.assertTrue(tobj == Rectangle((3, 1, 5, 9))) self.assertTrue(tobj == (3, 1, 5, 9)) self.assertFalse(tobj == (3, 1, 5, 9, 8)) self.assertFalse(tobj == [3, 1, 5, 9, 8]) self.assertFalse(tobj == {3, 1, 5, 9, 8})
def test_init(self): s = Point(1, 3) e = Point(5, 9) tobj = Rectangle(s, e) self.assertEqual(s, tobj.start) self.assertEqual(e, tobj.end) tobj = Rectangle(e, s) self.assertEqual(s, tobj.start) self.assertEqual(e, tobj.end)
def test_init_list(self): tobj = Rectangle((1, 3, 5, 9)) self.assertEqual(tobj.start, Point(1, 3)) tobj = Rectangle([1, 3, 5, 9]) self.assertEqual(tobj.start, Point(1, 3)) sobj = {1, 3, 5, 9} tobj = Rectangle(sobj) self.assertEqual(tobj.start, Point(1, 3))
def test_init_Points(self): tobj = Rectangle(Point(5, 9), Point(1, 3)) self.assertEqual(tobj.start, Point(1, 3)) tobj = Rectangle(Point(1, 3)) self.assertEqual(tobj.start, Point(0, 0)) self.assertEqual(tobj.end, Point(1, 3)) tobj = Rectangle(Point(-1, -3)) self.assertEqual(tobj.end, Point(0, 0)) self.assertEqual(tobj.start, Point(-1, -3))
def test_repr(self): src = Rectangle([100, 100, 300, 200]) dst = Rectangle([10, 10, 2000, 100]) tobj = DrawingContext(src, dst, border=0.25) self.assertEqual(Point(-100, -100), tobj.o_translate()) self.assertEqual(Point(960.0, 32.5), tobj.t_translate()) self.assertEqual(0.45, tobj.scale()) s_ref = 'DrawingContext(orig=Rectangle(Point(100,100),Point(300,200)),target=Rectangle(Point(10,10),Point(2000,100)),border=0.25)' self.assertEqual(s_ref, repr(tobj)) s_ref = '(orig=Rectangle(Point(100,100),Point(300,200)),target=[(10,10)-(2000,100)],border=0.25) -> o_translate=(-100,-100),scale=0.45,t_translate=(960.0,32.5)' self.assertEqual(s_ref, str(tobj))
def test_transpose(self): src = Rectangle([100, 100, 300, 200]) dst = Rectangle([10, 10, 210, 110]) ctx = DrawingContext(src, dst, border=0) self.assertEqual(Point(10, 10), ctx.transpose(Point(100, 100))) self.assertEqual(Point(210, 110), ctx.transpose(Point(300, 200))) ctx = DrawingContext(src, dst, border=0.1) self.assertEqual(Point(30, 20), ctx.transpose(Point(100, 100))) self.assertEqual(Point(190, 100), ctx.transpose(Point(300, 200))) ctx = DrawingContext(src, dst, border=0.5) self.assertEqual(Point(110, 60), ctx.transpose(Point(100, 100))) self.assertEqual(Point(110, 60), ctx.transpose(Point(300, 200))) ctx = DrawingContext(src, dst, border=1) self.assertEqual(Point(210, 110), ctx.transpose(Point(100, 100))) self.assertEqual(Point(10, 10), ctx.transpose(Point(300, 200)))
def test_transpose_back(self): src = Rectangle([100, 100, 300, 200]) dst = Rectangle([10, 10, 210, 110]) ctx = DrawingContext(src, dst, border=0) self.assertEqual(Point(100, 100), ctx.transposeBack(Point(10, 10))) self.assertEqual(Point(300, 200), ctx.transposeBack(Point(210, 110))) for src in [Point(100, 100), Point(300, 200)]: self.assertEqual(src, ctx.transposeBack(ctx.transpose(src))) ctx = DrawingContext(src, dst, border=0.1) for src in [Point(100, 100), Point(300, 200)]: self.assertEqual(src, ctx.transposeBack(ctx.transpose(src))) ctx = DrawingContext(src, dst, border=0.5) for src in [Point(100, 100), Point(300, 200)]: self.assertEqual(src, ctx.transposeBack(src)) ctx = DrawingContext(src, dst, border=1) for src in [Point(100, 100), Point(300, 200)]: p = ctx.transposeBack(ctx.transpose(src)) x, y = round(p.x), round(p.y) self.assertEqual(src, Point(x, y))
def test_contains_point(self): tobj = Rectangle([100, 100], [300, 300]) self.assertTrue(tobj.contains_point((200, 200))) self.assertTrue(tobj.contains_point((100, 100))) self.assertTrue(tobj.contains_point((300, 300))) self.assertFalse(tobj.contains_point((99, 100))) self.assertFalse(tobj.contains_point((100, 99))) self.assertFalse(tobj.contains_point((301, 100))) self.assertFalse(tobj.contains_point((100, 301)))
def test_init_simple(self): src = Rectangle([0, 0, 200, 100]) dst = Rectangle([0, 0, 200, 100]) tobj = DrawingContext(src, dst, border=0) self.assertEqual(Point(0, 0), tobj.o_translate()) self.assertEqual(Point(0, 0), tobj.t_translate()) self.assertEqual(1, tobj.scale()) src = Rectangle([0, 0, 200, 100]) dst = Rectangle([0, 0, 300, 100]) tobj = DrawingContext(src, dst, border=0) self.assertEqual(Point(0, 0), tobj.o_translate()) self.assertEqual(Point(50, 0), tobj.t_translate()) self.assertEqual(1, tobj.scale()) src = Rectangle([0, 0, 200, 100]) dst = Rectangle([0, 0, 200, 200]) tobj = DrawingContext(src, dst, border=0) self.assertEqual(Point(0, 0), tobj.o_translate()) self.assertEqual(Point(0, 50), tobj.t_translate()) self.assertEqual(1, tobj.scale())
def orig_rect(self, newValue): self._orig_rect = Rectangle(newValue) self.set_dirty()
def test_center(self): tobj = Rectangle([100, 100], [300, 300]) center = tobj.center() self.assertEqual(Point(200, 200), center)
def test_str(self): tobj = Rectangle([1, 3], [5, 9]) s = str(tobj) self.assertTrue(s == '[(1,3)-(5,9)]') self.assertTrue(f'{tobj}' == '[(1,3)-(5,9)]')
def test_repr(self): tobj = Rectangle([1, 3, 5, 9]) r = repr(tobj) self.assertEqual('Rectangle(Point(1,3),Point(5,9))', r)
def on_resize(self, event): self.canvas_area = Rectangle((0, 0, self.winfo_width(), self.winfo_height())) self.drawing_context.target_rect = self.canvas_area self.redraw()
def test_extent(self): s = Point(3, 9) e = Point(5, 1) tobj = Rectangle(s, e) self.assertEqual((2, 8), tobj.extent)
def test_height(self): s = Point(3, 9) e = Point(5, 1) tobj = Rectangle(s, e) self.assertEqual(8, tobj.height)
def test_width(self): s = Point(3, 9) e = Point(5, 1) tobj = Rectangle(s, e) self.assertEqual(2, tobj.width)
def init_context(self): self.drawing_area = Rectangle((0, 0, 1000, 1000)) self.canvas_area = Rectangle((0, 0, self.winfo_width(), self.winfo_height())) self.drawing_context = DrawingContext(orig=self.drawing_area, target=self.canvas_area, border=0.05)
def target_rect(self, newValue): self._target_rect = Rectangle(newValue) self.set_dirty()
def test_init_Rectangle(self): oRect = Rectangle((1, 3, 5, 9)) tobj = Rectangle(oRect) self.assertEqual(tobj.start, Point(1, 3))
def __init__(self, orig, target, border=0): self.orig_rect = Rectangle(orig) self.target_rect = Rectangle(target) self.target_border = border
class PyDrawCanvas(tk.Canvas): def __init__(self, master=None, **kwargs): super().__init__(master=master, **kwargs) self.elements = [] self.init_events() self.init_menubar() self.init_context() self.set_appicon() self.set_title() self.statusbar = None self.drp_Operation = None self.selectedObject = None # region Inits def set_appicon(self): self.master.tk.call('wm', 'iconphoto', self.master._w, PhotoImage(file='appicon.png')) def set_title(self): self.master.title("PyDraw by Festina Lente Software ") def init_events(self): self.focus_set() self.bind("<Key>", self.on_keypress) self.bind("<Configure>", self.on_resize) self.bind("<ButtonPress-1>", self.on_left_click) self.bind("<B1-Motion>", self.on_drag) self.bind("<ButtonRelease-1>", self.on_drop) self.master.protocol('WM_DELETE_WINDOW', self.on_closing) def init_menubar(self): self.menubar = MainMenu(self.master, self) def init_after_pack(self): self.create_statusbar() # endregion # region DrawingContext def init_context(self): self.drawing_area = Rectangle((0, 0, 1000, 1000)) self.canvas_area = Rectangle((0, 0, self.winfo_width(), self.winfo_height())) self.drawing_context = DrawingContext(orig=self.drawing_area, target=self.canvas_area, border=0.05) def transposeBack(self, pos): return self.drawing_context.transposeBack(pos) def transpose(self, pos): return self.drawing_context.transpose(pos) # endregion # region Events def on_keypress(self, event): ec = event.char ek = event.keysym if ek == 'Escape': self.selectedObject = None def on_resize(self, event): self.canvas_area = Rectangle((0, 0, self.winfo_width(), self.winfo_height())) self.drawing_context.target_rect = self.canvas_area self.redraw() def on_left_click(self, event): x, y = event.x, event.y d_point = self.drawing_context.transposeBack(Point(x, y)) if not self.drawing_area.contains_point(d_point): # ignore outside border return if self.selectedObject: self.drp_Operation = Drp_MoveObject(self, Point(x, y), self.selectedObject) else: newLine = LineElement(start=d_point, end=d_point + (1, 1)) self.add_element(newLine) self.redraw() self.drp_Operation = Drp_DrawLine(self, Point(x, y), newLine) self.selectedObject = newLine def on_object_click(self, object, event): self.selectedObject = object # print(f"on_object_click: event={event},object={object}") def on_closing(self): if not messagebox.askokcancel( 'Exit Tool', 'Do you really want to exit this tool?'): return self.master.destroy() def on_drag(self, event): if self.drp_Operation: self.drp_Operation.on_drag((event.x, event.y)) def on_drop(self, event): if self.drp_Operation: self.drp_Operation.on_drop((event.x, event.y)) self.drp_Operation = None # endregion # region Elements def add_element(self, drawing_element): self.elements.append(drawing_element) self.redraw() def new_drawing(self): self.setStatusMessage(text='Creating new drawing') self.elements = [] self.redraw() self.setStatusMessage(text='Created new drawing', resetInSecs=5) # endregion # region Drawing def redraw(self): self.delete("all") self.draw_border() for element in self.elements: element.draw_on_canvas(self, self.drawing_context) def draw_border(self): ctx = self.drawing_context p1 = ctx.transpose(self.drawing_area.start) p3 = ctx.transpose(self.drawing_area.end) p2, p4 = Point(p1.x, p3.y), Point(p3.x, p1.y) points = [p1, p2, p3, p4, p1] flat_points = [item for p in points for item in p.xy] self.create_line(*flat_points) # endregion # region Statusbar def create_statusbar(self): self.statusbar = StatusBar(master=self.master) self.statusbar.pack(fill=tk.X) def setStatusMessage(self, **kwargs): if self.statusbar: self.statusbar.setMessage(**kwargs) else: txt = kwargs.get("text", "") print(f'{datetime.now()} Status: {txt}') def setProgress(self, **kwargs): if self.statusbar: self.statusbar.setProgress(**kwargs) else: ptext = kwargs.get('text', '') value = kwargs.get('value', 0) range = kwargs.get('maximum', 0) progr = "" if not value \ else f'[{value}]' if not range \ else f'[{value}/{range}]' print(f'{datetime.now()} Progress: {progr} - {ptext}')