diff --git a/dvr_scan/app/region_editor.py b/dvr_scan/app/region_editor.py index 794cd67..05d8a25 100644 --- a/dvr_scan/app/region_editor.py +++ b/dvr_scan/app/region_editor.py @@ -169,7 +169,6 @@ def squared_distance(a: Point, b: Point) -> int: return (a.x - b.x) ** 2 + (a.y - b.y) ** 2 -# TODO: Allow translating polygons using middle mouse button. class RegionEditor: def __init__( self, @@ -220,6 +219,8 @@ def __init__( self._scale_widget: ttk.Scale = None self._pan_enabled: bool = False self._panning: bool = False + self._translate_enabled: bool = False + self._translating_shape: bool = False self._controls_window: tk.Toplevel = None self._region_selector: ttk.Combobox = None @@ -357,6 +358,8 @@ def _copy_scan_command_to_clipboard(self): def _set_cursor(self): if self._pan_enabled or self._panning: self._editor_canvas.config(cursor="fleur") + elif self._translate_enabled: + self._editor_canvas.config(cursor="fleur") elif self._hover_point is None: self._editor_canvas.config(cursor="crosshair") else: @@ -597,6 +600,18 @@ def set_pan_mode(mode: bool): self._root.bind("", lambda _: set_pan_mode(False)) self._root.bind("", lambda _: set_pan_mode(False)) + def set_translate_mode(mode: bool): + if self._dragging: + self._translate_enabled = False + else: + self._translate_enabled = mode + self._set_cursor() + + self._root.bind("", lambda _: set_translate_mode(True)) + self._root.bind("", lambda _: set_translate_mode(True)) + self._root.bind("", lambda _: set_translate_mode(False)) + self._root.bind("", lambda _: set_translate_mode(False)) + self._root.protocol("WM_DELETE_WINDOW", lambda: self._close(False)) self._root.bind("", lambda _: self._cancel_active_action()) @@ -607,9 +622,6 @@ def select_region(index): self._root.bind(f"{i + 1}", select_region(i)) - # TODO: If Shift is held down, allow translating current shape - # by left-click and drag. - def _close(self, should_scan: bool): if self._launched_from_app: self._root.destroy() @@ -1153,6 +1165,11 @@ def _handle_mouse_input(self, event, point: Point): if not inside_canvas: return + if self._translate_enabled: + self._translating_shape = True + self._drag_start = self._curr_mouse_pos + return + if not self._regions: logger.info("No regions to edit, add a new one by right clicking.") if self._hover_point is not None: @@ -1166,6 +1183,22 @@ def _handle_mouse_input(self, event, point: Point): self.active_region[self._hover_point] = self._curr_mouse_pos self._recalculate = False self._redraw = True + elif self._translating_shape: + # TODO: This can be optimized. + new_region = [] + for i in range(len(self.active_region)): + new_region.append( + Point( + x=self.active_region[i].x + + (self._curr_mouse_pos.x - self._drag_start.x), + y=self.active_region[i].y + + (self._curr_mouse_pos.y - self._drag_start.y), + ) + ) + self._regions[self._active_shape] = new_region + self._drag_start = self._curr_mouse_pos + self._recalculate = False + self._redraw = True elif self._pan_enabled or self._panning: if self._panning: self._editor_canvas.scan_dragto(point.x, point.y, gain=1) @@ -1194,6 +1227,9 @@ def _handle_mouse_input(self, event, point: Point): self._redraw = True self._dragging = False self._panning = False + if self._translating_shape: + self._translating_shape = False + self._commit() self._set_cursor() # Pan mode could have changed. self._draw() @@ -1219,6 +1255,8 @@ def _cancel_active_action(self) -> bool: self._dragging = False self._panning = False self._pan_enabled = False + self._translating_shape = False + self._translate_enabled = False self._set_cursor() self._draw()