From 08847ca91b0bca628299e24d16c64dad7e41d05f Mon Sep 17 00:00:00 2001 From: Isaiah Odhner Date: Tue, 12 Sep 2023 20:16:55 -0400 Subject: [PATCH] Fix Free-Form Select behavior when melding with negative coordinates --- README.md | 1 - src/textual_paint/ansi_art_document.py | 18 +++++++++++++++++- tests/test_snapshots.py | 5 ++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 55a0e14..5b63672 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,6 @@ To preview ANSI art files in file managers like Nautilus, Thunar, Nemo, or Caja, - The canvas flickers when zooming in with the Magnifier tool. - Some languages don't display correctly. - Large files can make the program very slow, as can magnifying the canvas. There is a 500 KB limit when opening files to prevent it from freezing. -- Free-Form Select stamping/finalizing is incorrect when the selection is off-screen to the left or top. - The status bar description can be left blank when selecting a menu item. (I think the `Leave` event can come after closing, once the mouse moves.) - Menu items like Copy/Cut/Paste are not grayed out when inapplicable. Only unimplemented items are grayed out. - ANSI files (.ans) are treated as UTF-8 when saving and loading, rather than CP437 or Windows-1252 or any other encodings. Unicode is nice and modern terminals support it, but it's not the standard for ANSI files. There isn't really a standard for ANSI files. diff --git a/src/textual_paint/ansi_art_document.py b/src/textual_paint/ansi_art_document.py index 1c8830b..d40b9c2 100644 --- a/src/textual_paint/ansi_art_document.py +++ b/src/textual_paint/ansi_art_document.py @@ -1106,4 +1106,20 @@ class Selection: target_region = self.region.intersection(Region(0, 0, document.width, document.height)) source_region = Region(target_region.x - self.region.x, target_region.y - self.region.y, self.contained_image.width, self.contained_image.height) - document.copy_region(source=self.contained_image, source_region=source_region, target_region=target_region, mask=self.mask) + # Offset mask due to account for the intersection. + # This is probably not the best way (or place) to do this. + # If refactoring, make sure to run: + # pytest -k test_free_form_select_meld_negative_coords + # (and then all the tests) + offset = target_region.offset - self.region.offset + if self.mask: + def sample(x: int, y: int) -> bool: + try: + return self.mask[y + offset.y][x + offset.x] + except IndexError: + return False + mask = [[sample(x, y) for x in range(source_region.width)] for y in range(source_region.height)] + else: + mask = None + + document.copy_region(source=self.contained_image, source_region=source_region, target_region=target_region, mask=mask) diff --git a/tests/test_snapshots.py b/tests/test_snapshots.py index c953360..8451ad4 100644 --- a/tests/test_snapshots.py +++ b/tests/test_snapshots.py @@ -289,9 +289,6 @@ def test_free_form_select(snap_compare: SnapCompareType): assert snap_compare(PAINT, run_before=automate_app, terminal_size=LARGER) -# Don't run, so that it doesn't overwrite the snapshot with --snapshot-update -# You can run it to see the diff, but it's disabled to prevent accidentally committing a bad snapshot. -@pytest.mark.xfail(run=False, reason="The Free-Form Select tool is currently buggy, melding incorrectly when off-screen to the left/top, but I've contrived the correct output for the test by disabling the deselect step at the end of automate_app and disabling the selection's border rendering in Canvas.render_line.") def test_free_form_select_meld_negative_coords(snap_compare: SnapCompareType): async def automate_app(pilot: Pilot[None]): await click_by_attr(pilot, "ToolsBox Button", "tooltip", "Fill With Color") @@ -301,7 +298,9 @@ def test_free_form_select_meld_negative_coords(snap_compare: SnapCompareType): await drag(pilot, '#editing_area', [Offset(19, 1), Offset(19, 1), Offset(18, 2), Offset(17, 2), Offset(15, 3), Offset(13, 4), Offset(6, 6), Offset(2, 8), Offset(0, 10), Offset(3, 2), Offset(2, 0), Offset(2, 1), Offset(2, 2), Offset(3, 2), Offset(5, 2), Offset(14, 14), Offset(1, 14), Offset(1, 13), Offset(4, 13), Offset(8, 12), Offset(12, 11), Offset(16, 11), Offset(20, 10), Offset(22, 10), Offset(23, 9), Offset(24, 9), Offset(25, 9), Offset(26, 9), Offset(26, 8), Offset(25, 8), Offset(23, 7), Offset(19, 6), Offset(15, 6), Offset(11, 5), Offset(6, 3), Offset(3, 2), Offset(2, 1), Offset(2, 0), Offset(3, 0), Offset(3, 0)]) await drag(pilot, '#canvas', [Offset(13, 8), Offset(13, 8), Offset(12, 8), Offset(12, 7), Offset(12, 6), Offset(11, 6), Offset(11, 5), Offset(10, 5), Offset(10, 4), Offset(9, 4), Offset(8, 3), Offset(8, 3)]) await pilot.press('ctrl+i') + await pilot.pause(0.5) await pilot.click('#editing_area', offset=Offset(0, 20)) # deselect + await pilot.pause(0.5) assert snap_compare(PAINT, run_before=automate_app, terminal_size=LARGER)