From 59f1f8e671e99a56a5b54e346a8b78ed1d2a5505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Obr=C4=99bski?= Date: Sun, 16 Feb 2025 19:36:13 +0100 Subject: [PATCH 01/10] Add tests for notes overlay script --- internal/notes/note_manager.lua | 9 +- notes.lua | 16 +-- test/gui/journal.lua | 2 - test/overlay/notes.lua | 204 ++++++++++++++++++++++++++++++++ 4 files changed, 217 insertions(+), 14 deletions(-) create mode 100644 test/overlay/notes.lua diff --git a/internal/notes/note_manager.lua b/internal/notes/note_manager.lua index 6ba76555be..56342abb11 100644 --- a/internal/notes/note_manager.lua +++ b/internal/notes/note_manager.lua @@ -39,7 +39,6 @@ function NoteManager:init() frame={t=1,h=3}, frame_style=gui.FRAME_INTERIOR, init_text=self.note and self.note.point.name or '', - -- init_cursor=self.note and #self.note.point.name + 1 or 1, one_line_mode=true }, widgets.HotkeyLabel { @@ -97,11 +96,11 @@ function NoteManager:init() end function NoteManager:setNotePos(note_pos) - self.notes_pos = note_pos + self.note_pos = note_pos end function NoteManager:createNote() - local cursor_pos = self.notes_pos or guidm.getCursorPos() + local cursor_pos = self.note_pos or guidm.getCursorPos() if cursor_pos == nil then dfhack.printerr('Enable keyboard cursor to add a note.') return @@ -150,8 +149,8 @@ function NoteManager:saveNote() self.note.point.name = name self.note.point.comment = comment - if self.notes_pos then - self.note.pos=self.notes_pos + if self.note_pos then + self.note.pos=self.note_pos end if self.on_update then diff --git a/notes.lua b/notes.lua index f9cd2a854c..84244955de 100644 --- a/notes.lua +++ b/notes.lua @@ -4,12 +4,14 @@ local overlay = require('plugins.overlay') local guidm = require('gui.dwarfmode') local note_manager = reqscript('internal/notes/note_manager') -local green_pin = dfhack.textures.loadTileset( - 'hack/data/art/note_green_pin_map.png', - 32, - 32, - true -) +textures = { + green_pin = dfhack.textures.loadTileset( + 'hack/data/art/note_green_pin_map.png', + 32, + 32, + true + ) +} NotesOverlay = defclass(NotesOverlay, overlay.OverlayWidget) NotesOverlay.ATTRS{ @@ -113,7 +115,7 @@ function NotesOverlay:onRenderFrame(dc) dc:map(true) - local texpos = dfhack.textures.getTexposByHandle(green_pin[1]) + local texpos = dfhack.textures.getTexposByHandle(textures.green_pin[1]) dc:pen({fg=COLOR_BLACK, bg=COLOR_LIGHTCYAN, tile=texpos}) for _, note in pairs(self.visible_notes) do diff --git a/test/gui/journal.lua b/test/gui/journal.lua index 19975a7379..3ca7450c12 100644 --- a/test/gui/journal.lua +++ b/test/gui/journal.lua @@ -6,8 +6,6 @@ config = { mode = 'fortress' } -local df_major_version = tonumber(dfhack.getCompiledDFVersion():match('%d+')) - local function simulate_input_keys(...) local keys = {...} for _,key in ipairs(keys) do diff --git a/test/overlay/notes.lua b/test/overlay/notes.lua new file mode 100644 index 0000000000..b2dc4f7a5b --- /dev/null +++ b/test/overlay/notes.lua @@ -0,0 +1,204 @@ +local gui = require('gui') +local overlay = require('plugins.overlay') +local guidm = require('gui.dwarfmode') +local utils = require('utils') +local notes_textures = reqscript('notes').textures + +local waypoints = df.global.plotinfo.waypoints +local map_points = df.global.plotinfo.waypoints.points + +config = { + target = 'notes', + mode = 'fortress' +} + +local map_points_backup = nil + +local function install_notes_overlay(options) + options = options or {} + + map_points_backup = utils.clone(map_points) + map_points:resize(0) + + overlay.rescan() + overlay.overlay_command({'enable', 'notes.map_notes'}) + -- if overlay + local overlay_state = overlay.get_state() + if not overlay_state.config['notes.map_notes'].enabled then + qerror('can not enable notes.map_notes overlay') + end + + return overlay_state.db['notes.map_notes'].widget +end + +local function reload_notes() + overlay.overlay_command({'trigger', 'notes.map_notes'}) +end + +local function cleanup(notes_overlay) + if notes_overlay.note_manager then + notes_overlay.note_manager:dismiss() + end + + df.global.plotinfo.waypoints.points:resize(#map_points_backup) + for ind, map_point in ipairs(map_points_backup) do + df.global.plotinfo.waypoints.points[ind - 1] = map_point + end + map_points_backup = nil + + reload_notes() +end + +local function add_note(notes_overlay, pos, name, comment) + df.global.cursor = copyall(pos) + + local cmd_result = overlay.overlay_command({ + 'trigger', 'notes.map_notes', 'add' + }) + + notes_overlay.note_manager.subviews.name:setText(name) + notes_overlay.note_manager.subviews.comment:setText(comment) + + gui.simulateInput(dfhack.gui.getCurViewscreen(true), 'CUSTOM_CTRL_ENTER') +end + + +function test.load_notes_overlay() + local notes_overlay = install_notes_overlay() + expect.ne(notes_overlay, nil) + cleanup(notes_overlay) +end + +function test.trigger_add_new_note_modal() + local notes_overlay = install_notes_overlay() + + local cmd_result = overlay.overlay_command({ + 'trigger', 'notes.map_notes', 'add' + }) + + expect.eq(cmd_result, true) + expect.ne(notes_overlay.note_manager, nil) + expect.eq(notes_overlay.note_manager.visible, true) + + cleanup(notes_overlay) +end + +function test.render_existing_notes() + local notes_overlay = install_notes_overlay() + + local pos_1 = {x=10, y=20, z=0} + local pos_2 = {x=10, y=20, z=0} + local pos_3 = {x=10, y=20, z=0} + + add_note(notes_overlay, pos_1, 'note 1', 'first note') + add_note(notes_overlay, pos_2, 'note 2', 'second note') + add_note(notes_overlay, pos_3, 'note 3', 'last note') + + reload_notes() + + local viewport = guidm.Viewport.get() + + local pin_textpos = dfhack.textures.getTexposByHandle( + notes_textures.green_pin[1] + ) + + for _, pos in ipairs({pos_1, pos_2, pos_3}) do + dfhack.gui.revealInDwarfmodeMap(pos) + + -- TODO: find better way to wait for overlay re-render + delay(10) + + local screen_pos = viewport:tileToScreen(pos) + local pen = dfhack.screen.readTile(screen_pos.x, screen_pos.y, true) + expect.eq(pen and pen.tile, pin_textpos) + end + + cleanup(notes_overlay) +end + +function test.edit_clicked_note() + local notes_overlay = install_notes_overlay() + + local pos = {x=10, y=20, z=0} + add_note(notes_overlay, pos, 'note 1', 'note to edit') + add_note(notes_overlay, {x=20, y=10, z=2}, 'note 2', 'other note') + add_note(notes_overlay, {x=0, y=10, z=5}, 'note 3', 'another note') + + reload_notes() + dfhack.screen.invalidate() + dfhack.gui.revealInDwarfmodeMap(pos) + + -- TODO: find better way to wait for overlay re-render + delay(10) + + notes_overlay:updateLayout() + + local viewport = guidm.Viewport.get() + local screen_pos = viewport:tileToScreen(pos) + + local rect = gui.ViewRect{rect=notes_overlay.frame_rect} + + -- should not be a test function to map screen tile to mouse pos? + df.global.gps.precise_mouse_x = screen_pos.x * df.global.gps.viewport_zoom_factor / 4 + df.global.gps.precise_mouse_y = screen_pos.y * df.global.gps.viewport_zoom_factor / 4 + + local screen = dfhack.gui.getCurViewscreen(true) + gui.simulateInput(screen, { + _MOUSE_L=true, + }) + + local note_manager = notes_overlay.note_manager + expect.ne(note_manager, nil) + + expect.eq(note_manager.subviews.name:getText(), 'note 1') + expect.eq(note_manager.subviews.comment:getText(), 'note to edit') + + note_manager.subviews.name:setText('edited note 1') + note_manager.subviews.comment:setText('edited comment') + + gui.simulateInput(dfhack.gui.getCurViewscreen(true), 'CUSTOM_CTRL_ENTER') + + expect.eq(map_points[0].name, 'edited note 1') + expect.eq(map_points[0].comment, 'edited comment') + + cleanup(notes_overlay) +end + +function test.delete_clicked_note() + local notes_overlay = install_notes_overlay() + + local pos = {x=10, y=20, z=0} + add_note(notes_overlay, {x=20, y=10, z=2}, 'note 1', 'note to edit') + add_note(notes_overlay, pos, 'note 2', 'other note') + add_note(notes_overlay, {x=0, y=10, z=5}, 'note 3', 'another note') + + reload_notes() + dfhack.screen.invalidate() + dfhack.gui.revealInDwarfmodeMap(pos) + + notes_overlay:updateLayout() + + local viewport = guidm.Viewport.get() + local screen_pos = viewport:tileToScreen(pos) + + local rect = gui.ViewRect{rect=notes_overlay.frame_rect} + + -- should not be a test function to map screen tile to mouse pos? + df.global.gps.precise_mouse_x = screen_pos.x * df.global.gps.viewport_zoom_factor / 4 + df.global.gps.precise_mouse_y = screen_pos.y * df.global.gps.viewport_zoom_factor / 4 + + local screen = dfhack.gui.getCurViewscreen(true) + gui.simulateInput(screen, { + _MOUSE_L=true, + }) + + expect.eq(#map_points, 3) + + gui.simulateInput(dfhack.gui.getCurViewscreen(true), 'CUSTOM_CTRL_D') + + expect.eq(#map_points, 2) + expect.eq(map_points[0].name, 'note 1') + expect.eq(map_points[1].name, 'note 3') + + cleanup(notes_overlay) +end From 4c98e7e6cc7735c695b45fc925f3cabe4b8d0654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Obr=C4=99bski?= Date: Mon, 17 Feb 2025 18:51:19 +0100 Subject: [PATCH 02/10] Make notes script tests only test on current visible screen We do not currently have an obvious way to center map on notes in tests and force-render map. Without it, we can test reliably only on current visible screen --- test/overlay/notes.lua | 66 ++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/test/overlay/notes.lua b/test/overlay/notes.lua index b2dc4f7a5b..704ceba52e 100644 --- a/test/overlay/notes.lua +++ b/test/overlay/notes.lua @@ -86,9 +86,14 @@ end function test.render_existing_notes() local notes_overlay = install_notes_overlay() - local pos_1 = {x=10, y=20, z=0} - local pos_2 = {x=10, y=20, z=0} - local pos_3 = {x=10, y=20, z=0} + local viewport = guidm.Viewport.get() + + local half_x = math.floor((viewport.x1 + viewport.x2) / 2) + local half_y = math.floor((viewport.y1 + viewport.y2) / 2) + + local pos_1 = {x=half_x, y=viewport.y1, z=viewport.z} + local pos_2 = {x=viewport.x1, y=half_y, z=viewport.z} + local pos_3 = {x=half_x, y=half_y, z=viewport.z} add_note(notes_overlay, pos_1, 'note 1', 'first note') add_note(notes_overlay, pos_2, 'note 2', 'second note') @@ -96,17 +101,12 @@ function test.render_existing_notes() reload_notes() - local viewport = guidm.Viewport.get() - local pin_textpos = dfhack.textures.getTexposByHandle( notes_textures.green_pin[1] ) for _, pos in ipairs({pos_1, pos_2, pos_3}) do - dfhack.gui.revealInDwarfmodeMap(pos) - - -- TODO: find better way to wait for overlay re-render - delay(10) + notes_overlay:render(gui.Painter.new()) local screen_pos = viewport:tileToScreen(pos) local pen = dfhack.screen.readTile(screen_pos.x, screen_pos.y, true) @@ -119,22 +119,22 @@ end function test.edit_clicked_note() local notes_overlay = install_notes_overlay() - local pos = {x=10, y=20, z=0} - add_note(notes_overlay, pos, 'note 1', 'note to edit') - add_note(notes_overlay, {x=20, y=10, z=2}, 'note 2', 'other note') - add_note(notes_overlay, {x=0, y=10, z=5}, 'note 3', 'another note') + local viewport = guidm.Viewport.get() - reload_notes() - dfhack.screen.invalidate() - dfhack.gui.revealInDwarfmodeMap(pos) + local half_x = math.floor((viewport.x1 + viewport.x2) / 2) + local half_y = math.floor((viewport.y1 + viewport.y2) / 2) - -- TODO: find better way to wait for overlay re-render - delay(10) + local pos_1 = {x=half_x, y=viewport.y1, z=viewport.z} + local pos_2 = {x=viewport.x1, y=half_y, z=viewport.z} + local pos_3 = {x=half_x, y=half_y, z=viewport.z} - notes_overlay:updateLayout() + add_note(notes_overlay, pos_1, 'note 1', 'note to edit') + add_note(notes_overlay, pos_2, 'note 2', 'other note') + add_note(notes_overlay, pos_3, 'note 3', 'another note') - local viewport = guidm.Viewport.get() - local screen_pos = viewport:tileToScreen(pos) + reload_notes() + + local screen_pos = viewport:tileToScreen(pos_1) local rect = gui.ViewRect{rect=notes_overlay.frame_rect} @@ -167,19 +167,23 @@ end function test.delete_clicked_note() local notes_overlay = install_notes_overlay() - local pos = {x=10, y=20, z=0} - add_note(notes_overlay, {x=20, y=10, z=2}, 'note 1', 'note to edit') - add_note(notes_overlay, pos, 'note 2', 'other note') - add_note(notes_overlay, {x=0, y=10, z=5}, 'note 3', 'another note') - reload_notes() - dfhack.screen.invalidate() - dfhack.gui.revealInDwarfmodeMap(pos) + local viewport = guidm.Viewport.get() - notes_overlay:updateLayout() + local half_x = math.floor((viewport.x1 + viewport.x2) / 2) + local half_y = math.floor((viewport.y1 + viewport.y2) / 2) - local viewport = guidm.Viewport.get() - local screen_pos = viewport:tileToScreen(pos) + local pos_1 = {x=half_x, y=viewport.y1, z=viewport.z} + local pos_2 = {x=viewport.x1, y=half_y, z=viewport.z} + local pos_3 = {x=half_x, y=half_y, z=viewport.z} + + add_note(notes_overlay, pos_1, 'note 1', 'note to edit') + add_note(notes_overlay, pos_2, 'note 2', 'other note') + add_note(notes_overlay, pos_3, 'note 3', 'another note') + + reload_notes() + + local screen_pos = viewport:tileToScreen(pos_2) local rect = gui.ViewRect{rect=notes_overlay.frame_rect} From 5fb75bbf764ec6111455b73d12c0dca6815bff36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Obr=C4=99bski?= Date: Mon, 17 Feb 2025 19:15:03 +0100 Subject: [PATCH 03/10] Add basic tests for gui/notes widget --- gui/notes.lua | 2 +- test/gui/notes.lua | 86 ++++++++++++++++++++++++++++++++++++++++++ test/overlay/notes.lua | 2 - 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 test/gui/notes.lua diff --git a/gui/notes.lua b/gui/notes.lua index 47b072887e..2e3a80f484 100644 --- a/gui/notes.lua +++ b/gui/notes.lua @@ -348,7 +348,7 @@ function NotesScreen:onDismiss() view = nil end -function main(options) +function main() if not dfhack.isMapLoaded() or not dfhack.world.isFortressMode() then qerror('notes requires a fortress map to be loaded') end diff --git a/test/gui/notes.lua b/test/gui/notes.lua new file mode 100644 index 0000000000..941faf5e80 --- /dev/null +++ b/test/gui/notes.lua @@ -0,0 +1,86 @@ +local gui = require('gui') +local gui_notes = reqscript('gui/notes') +local utils = require('utils') + +-- local guidm = require('gui.dwarfmode') + +config = { + target = 'gui/notes', + mode = 'fortress' +} + +local waypoints = df.global.plotinfo.waypoints +local map_points = df.global.plotinfo.waypoints.points + +local map_points_backup = nil + +local function arrange_notes(notes) + map_points_backup = utils.clone(map_points) + map_points:resize(0) + + for _, note in ipairs(notes or {}) do + map_points:insert("#", { + new=true, + + id = waypoints.next_point_id, + tile=88, + fg_color=7, + bg_color=0, + name=note.name, + comment=note.comment, + pos=note.pos + }) + end +end + +local function arrange_gui_notes(options) + options = options or {} + + arrange_notes(options.notes) + + gui_notes.main() + + local gui_notes = gui_notes.view + + gui_notes:updateLayout() + gui_notes:onRender() + + return gui_notes +end + +local function cleanup(gui_notes) + gui_notes:dismiss() + + df.global.plotinfo.waypoints.points:resize(#map_points_backup) + for ind, map_point in ipairs(map_points_backup) do + df.global.plotinfo.waypoints.points[ind - 1] = map_point + end + map_points_backup = nil +end + +function test.load_gui_notes() + local gui_notes = arrange_gui_notes() + expect.eq(gui_notes.visible, true) + cleanup(gui_notes) +end + +function test.provide_notes_list() + local notes = { + {name='note 1', comment='comment 1', pos={x=1, y=1, z=1}}, + {name='note 2', comment='comment 2', pos={x=2, y=2, z=2}}, + {name='note 3', comment='comment 3', pos={x=3, y=3, z=3}}, + } + + local gui_notes = arrange_gui_notes({ notes=notes }) + local note_list = gui_notes.subviews.note_list:getChoices() + + for ind, note in ipairs(notes) do + local gui_note = note_list[ind] + expect.eq(gui_note.text, note.name) + expect.eq(gui_note.point.comment, note.comment) + expect.table_eq(gui_note.point.pos, note.pos) + end + + expect.eq(gui_notes.visible, true) + cleanup(gui_notes) +end diff --git a/test/overlay/notes.lua b/test/overlay/notes.lua index 704ceba52e..b096f30399 100644 --- a/test/overlay/notes.lua +++ b/test/overlay/notes.lua @@ -62,7 +62,6 @@ local function add_note(notes_overlay, pos, name, comment) gui.simulateInput(dfhack.gui.getCurViewscreen(true), 'CUSTOM_CTRL_ENTER') end - function test.load_notes_overlay() local notes_overlay = install_notes_overlay() expect.ne(notes_overlay, nil) @@ -167,7 +166,6 @@ end function test.delete_clicked_note() local notes_overlay = install_notes_overlay() - local viewport = guidm.Viewport.get() local half_x = math.floor((viewport.x1 + viewport.x2) / 2) From af1cae28d90956839cc5ff6db5ba4e6aae290f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Obr=C4=99bski?= Date: Wed, 19 Feb 2025 22:50:28 +0100 Subject: [PATCH 04/10] Add tests for filtering, centering, preview and delete gui/notes --- gui/notes.lua | 55 ++++++++------- test/gui/notes.lua | 162 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 190 insertions(+), 27 deletions(-) diff --git a/gui/notes.lua b/gui/notes.lua index 2e3a80f484..0f4d71f694 100644 --- a/gui/notes.lua +++ b/gui/notes.lua @@ -38,38 +38,43 @@ function NotesWindow:init() self.note_manager = nil self.curr_search_phrase = nil - self:addviews{ + local left_panel_content = { widgets.Panel{ - view_id='note_list_panel', - frame={l=0, w=NOTE_LIST_RESIZE_MIN.w, t=0, b=1}, - visible=true, - frame_inset={l=1,t=1,b=1,r=1}, - autoarrange_subviews=true, + frame={l=0,h=3}, + frame_style=gui.FRAME_INTERIOR, subviews={ - widgets.TextArea{ + widgets.EditField{ view_id='search', - frame={l=0,h=3}, - frame_style=gui.FRAME_INTERIOR, - one_line_mode=true, - on_text_change=self:callback('loadFilteredNotes'), + on_change=self:callback('loadFilteredNotes'), on_submit=function() self.subviews.note_list:submit() end }, - widgets.List{ - view_id='note_list', - frame={l=0,b=2}, - frame_inset={t=1}, - row_height=1, - on_select=function (ind, note) - self:loadNote(note) - end, - on_submit=function (ind, note) - self:loadNote(note) - dfhack.gui.pauseRecenter(note.point.pos) - end - }, - }, + } + }, + widgets.List{ + view_id='note_list', + frame={l=0,b=2}, + frame_inset={t=1}, + row_height=1, + on_select=function (ind, note) + self:loadNote(note) + end, + on_submit=function (ind, note) + self:loadNote(note) + dfhack.gui.pauseRecenter(note.point.pos) + end + }, + } + + self:addviews{ + widgets.Panel{ + view_id='note_list_panel', + frame={l=0, w=NOTE_LIST_RESIZE_MIN.w, t=0, b=1}, + visible=true, + frame_inset={l=1,t=1,b=1,r=1}, + autoarrange_subviews=true, + subviews=left_panel_content, }, widgets.HotkeyLabel{ view_id='create', diff --git a/test/gui/notes.lua b/test/gui/notes.lua index 941faf5e80..9a938b240a 100644 --- a/test/gui/notes.lua +++ b/test/gui/notes.lua @@ -1,6 +1,8 @@ local gui = require('gui') local gui_notes = reqscript('gui/notes') local utils = require('utils') +local guidm = require('gui.dwarfmode') + -- local guidm = require('gui.dwarfmode') @@ -22,7 +24,7 @@ local function arrange_notes(notes) map_points:insert("#", { new=true, - id = waypoints.next_point_id, + id=waypoints.next_point_id, tile=88, fg_color=7, bg_color=0, @@ -30,6 +32,8 @@ local function arrange_notes(notes) comment=note.comment, pos=note.pos }) + + waypoints.next_point_id = waypoints.next_point_id + 1 end end @@ -81,6 +85,160 @@ function test.provide_notes_list() expect.table_eq(gui_note.point.pos, note.pos) end - expect.eq(gui_notes.visible, true) + cleanup(gui_notes) +end + +function test.auto_select_first_note() + local notes = { + {name='green note 1', comment='comment 1', pos={x=1, y=1, z=1}}, + {name='green note 2', comment='comment 2', pos={x=2, y=2, z=2}}, + {name='blue note 3', comment='comment 3', pos={x=3, y=3, z=3}}, + } + + local gui_notes = arrange_gui_notes({ notes=notes }) + expect.eq(gui_notes.subviews.name.text_to_wrap, 'green note 1') + expect.eq(gui_notes.subviews.comment.text_to_wrap, 'comment 1') + + cleanup(gui_notes) +end + +function test.select_on_arrow_up_down() + local notes = { + {name='green note 1', comment='comment 1', pos={x=1, y=1, z=1}}, + {name='green note 2', comment='comment 2', pos={x=2, y=2, z=2}}, + {name='blue note 3', comment='comment 3', pos={x=3, y=3, z=3}}, + } + + local gui_notes = arrange_gui_notes({ notes=notes }) + local screen = dfhack.gui.getCurViewscreen(true) + + gui.simulateInput(screen, 'KEYBOARD_CURSOR_DOWN') + expect.eq(gui_notes.subviews.name.text_to_wrap, 'green note 2') + expect.eq(gui_notes.subviews.comment.text_to_wrap, 'comment 2') + + gui.simulateInput(screen, 'KEYBOARD_CURSOR_DOWN') + expect.eq(gui_notes.subviews.name.text_to_wrap, 'blue note 3') + expect.eq(gui_notes.subviews.comment.text_to_wrap, 'comment 3') + + gui.simulateInput(screen, 'KEYBOARD_CURSOR_DOWN') + expect.eq(gui_notes.subviews.name.text_to_wrap, 'green note 1') + expect.eq(gui_notes.subviews.comment.text_to_wrap, 'comment 1') + + gui.simulateInput(screen, 'KEYBOARD_CURSOR_UP') + expect.eq(gui_notes.subviews.name.text_to_wrap, 'blue note 3') + expect.eq(gui_notes.subviews.comment.text_to_wrap, 'comment 3') + + gui.simulateInput(screen, 'KEYBOARD_CURSOR_UP') + expect.eq(gui_notes.subviews.name.text_to_wrap, 'green note 2') + expect.eq(gui_notes.subviews.comment.text_to_wrap, 'comment 2') + + cleanup(gui_notes) +end + +function test.center_at_submit_note() + local notes = { + {name='green note 1', comment='comment 1', pos={x=1, y=1, z=1}}, + {name='green note 2', comment='comment 2', pos={x=2, y=2, z=2}}, + {name='blue note 3', comment='comment 3', pos={x=3, y=3, z=3}}, + } + + local gui_notes = arrange_gui_notes({ notes=notes }) + local screen = dfhack.gui.getCurViewscreen(true) + + -- it would be best to check viewport, but it's not updated instantly + -- and I do not know way how to force it + -- local viewport = guidm.Viewport.get() + + local last_recenter_pos = nil + mock.patch(dfhack.gui, 'pauseRecenter', function (pos) + last_recenter_pos = pos + end, function () + gui.simulateInput(screen, 'KEYBOARD_CURSOR_DOWN') + gui.simulateInput(screen, 'SELECT') + + expect.eq(last_recenter_pos.x, 2) + expect.eq(last_recenter_pos.y, 2) + expect.eq(last_recenter_pos.z, 2) + + gui.simulateInput(screen, 'KEYBOARD_CURSOR_DOWN') + gui.simulateInput(screen, 'SELECT') + + expect.eq(last_recenter_pos.x, 3) + expect.eq(last_recenter_pos.y, 3) + expect.eq(last_recenter_pos.z, 3) + end) + + cleanup(gui_notes) +end + +function test.filter_notes() + local notes = { + {name='green note 1', comment='comment 1', pos={x=1, y=1, z=1}}, + {name='green note 2', comment='comment 2', pos={x=2, y=2, z=2}}, + {name='blue note 3', comment='comment 3', pos={x=3, y=3, z=3}}, + } + + local gui_notes = arrange_gui_notes({ notes=notes }) + gui_notes.subviews.search:setText('green') + + local note_list = gui_notes.subviews.note_list:getChoices() + expect.eq(#note_list, 2) + + for ind, note in ipairs({table.unpack(notes, 1, 2)}) do + local gui_note = note_list[ind] + expect.eq(gui_note.text, note.name) + expect.eq(gui_note.point.comment, note.comment) + expect.table_eq(gui_note.point.pos, note.pos) + end + + expect.eq(gui_notes.subviews.name.text_to_wrap, 'green note 1') + expect.eq(gui_notes.subviews.comment.text_to_wrap, 'comment 1') + + gui_notes.subviews.search:setText('blue') + + local note_list = gui_notes.subviews.note_list:getChoices() + expect.eq(#note_list, 1) + + expect.eq(note_list[1].text, notes[3].name) + expect.eq(note_list[1].point.comment, notes[3].comment) + expect.table_eq(note_list[1].point.pos, notes[3].pos) + + expect.eq(gui_notes.subviews.name.text_to_wrap, 'blue note 3') + expect.eq(gui_notes.subviews.comment.text_to_wrap, 'comment 3') + + gui_notes.subviews.search:setText('red') + + local note_list = gui_notes.subviews.note_list:getChoices() + expect.eq(#note_list, 0) + + cleanup(gui_notes) +end + +function test.delete_note() + local notes = { + {name='green note 1', comment='comment 1', pos={x=1, y=1, z=1}}, + {name='green note 2', comment='comment 2', pos={x=2, y=2, z=2}}, + {name='blue note 3', comment='comment 3', pos={x=3, y=3, z=3}}, + } + + local gui_notes = arrange_gui_notes({ notes=notes }) + local screen = dfhack.gui.getCurViewscreen(true) + + gui.simulateInput(screen, 'KEYBOARD_CURSOR_DOWN') + gui.simulateInput(screen, 'CUSTOM_CTRL_D') + + local note_list = gui_notes.subviews.note_list:getChoices() + expect.eq(#note_list, 2) + + for ind, note in ipairs({notes[1], notes[3]}) do + local gui_note = note_list[ind] + expect.eq(gui_note.text, note.name) + expect.eq(gui_note.point.comment, note.comment) + expect.table_eq(gui_note.point.pos, note.pos) + end + + expect.eq(gui_notes.subviews.name.text_to_wrap, 'blue note 3') + expect.eq(gui_notes.subviews.comment.text_to_wrap, 'comment 3') + cleanup(gui_notes) end From 2269cbe2b545fc77885709581648d5d815e4f33c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Obr=C4=99bski?= Date: Thu, 20 Feb 2025 07:13:07 +0100 Subject: [PATCH 05/10] Add edit note gui/notes test --- gui/notes.lua | 5 +++++ test/gui/notes.lua | 47 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/gui/notes.lua b/gui/notes.lua index 0f4d71f694..149e210260 100644 --- a/gui/notes.lua +++ b/gui/notes.lua @@ -350,6 +350,11 @@ function NotesScreen:onDismiss() if self.should_disable_overlay then overlay.overlay_command({'disable', 'notes.map_notes'}) end + + if self.subviews.notes_window.note_manager then + self.subviews.notes_window.note_manager:dismiss() + end + view = nil end diff --git a/test/gui/notes.lua b/test/gui/notes.lua index 9a938b240a..83013d37ca 100644 --- a/test/gui/notes.lua +++ b/test/gui/notes.lua @@ -2,9 +2,7 @@ local gui = require('gui') local gui_notes = reqscript('gui/notes') local utils = require('utils') local guidm = require('gui.dwarfmode') - - --- local guidm = require('gui.dwarfmode') +local overlay = require('plugins.overlay') config = { target = 'gui/notes', @@ -49,7 +47,11 @@ local function arrange_gui_notes(options) gui_notes:updateLayout() gui_notes:onRender() - return gui_notes + -- for some reasons running tests remove all overlays, + -- but there are need for gui/notes tests + overlay.rescan() + + return gui_notes, gui_notes.subviews.notes_window end local function cleanup(gui_notes) @@ -214,6 +216,43 @@ function test.filter_notes() cleanup(gui_notes) end +function test.edit_note() + local notes = { + {name='green note 1', comment='comment 1', pos={x=1, y=1, z=1}}, + {name='green note 2', comment='comment 2', pos={x=2, y=2, z=2}}, + {name='blue note 3', comment='comment 3', pos={x=3, y=3, z=3}}, + } + + local gui_notes, gui_notes_window = arrange_gui_notes({ notes=notes }) + local screen = dfhack.gui.getCurViewscreen(true) + + gui.simulateInput(screen, 'KEYBOARD_CURSOR_DOWN') + gui.simulateInput(screen, 'CUSTOM_CTRL_E') + + local note_manager = gui_notes_window.note_manager + expect.ne(note_manager, nil) + + expect.eq(note_manager.subviews.name:getText(), 'green note 2') + expect.eq(note_manager.subviews.comment:getText(), 'comment 2') + + note_manager.subviews.name:setText('updated green note 2') + note_manager.subviews.comment:setText('updated comment 2') + local screen = dfhack.gui.getCurViewscreen(true) + printall(screen.widgets) + gui.simulateInput(dfhack.gui.getCurViewscreen(true), 'CUSTOM_CTRL_ENTER') + + local note_list = gui_notes.subviews.note_list:getChoices() + expect.eq(#note_list, 3) + + local updated_note = note_list[2] + + expect.eq(updated_note.text, 'updated green note 2') + expect.eq(updated_note.point.name, 'updated green note 2') + expect.eq(updated_note.point.comment, 'updated comment 2') + + cleanup(gui_notes) +end + function test.delete_note() local notes = { {name='green note 1', comment='comment 1', pos={x=1, y=1, z=1}}, From 038391602b9f8a68a439ab777c8f8d713a41ca08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Obr=C4=99bski?= Date: Sun, 23 Feb 2025 08:20:31 +0100 Subject: [PATCH 06/10] Add create new note gui/notes test --- gui/notes.lua | 20 ++++++-------- test/gui/notes.lua | 68 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/gui/notes.lua b/gui/notes.lua index 149e210260..242e9aa8cc 100644 --- a/gui/notes.lua +++ b/gui/notes.lua @@ -9,6 +9,7 @@ local overlay = require 'plugins.overlay' local utils = require 'utils' local note_manager = reqscript('internal/notes/note_manager') +local notes_textures = reqscript('notes').textures local map_points = df.global.plotinfo.waypoints.points @@ -17,13 +18,6 @@ local RESIZE_MIN = {w=65, h=30} local NOTE_SEARCH_BATCH_SIZE = 25 local OVERLAY_NAME = 'notes.map_notes' -local green_pin = dfhack.textures.loadTileset( - 'hack/data/art/note_green_pin_map.png', - 32, - 32, - true -) - NotesWindow = defclass(NotesWindow, widgets.Window) NotesWindow.ATTRS { frame_title='DF Notes', @@ -253,6 +247,7 @@ NotesScreen = defclass(NotesScreen, gui.ZScreen) NotesScreen.ATTRS { focus_path='gui/notes', pass_movement_keys=true, + enable_selector_blink = true, } function NotesScreen:init() @@ -283,7 +278,7 @@ function NotesScreen:onInput(keys) if (keys.SELECT or keys._MOUSE_L) then self.adding_note_pos = dfhack.gui.getMousePos() - local manager = note_manager.NoteManager{ + local note_manager = note_manager.NoteManager{ note=nil, on_update=function() dfhack.run_command_silent('overlay trigger notes.map_notes') @@ -294,7 +289,8 @@ function NotesScreen:onInput(keys) self:stopNoteAdd() end }:show() - manager:setNotePos(self.adding_note_pos) + note_manager:setNotePos(self.adding_note_pos) + self.subviews.notes_window.note_manager = note_manager return true elseif (keys.LEAVESCREEN or keys._MOUSE_R)then @@ -309,7 +305,7 @@ end function NotesScreen:onRenderFrame(dc, rect) NotesScreen.super.onRenderFrame(self, dc, rect) - if not dfhack.screen.inGraphicsMode() and not gui.blink_visible(500) then + if self.enable_selector_blink and not gui.blink_visible(500) then return end @@ -321,7 +317,9 @@ function NotesScreen:onRenderFrame(dc, rect) local function get_overlay_pen(pos) if same_xy(curr_pos, pos) then - local texpos = dfhack.textures.getTexposByHandle(green_pin[1]) + local texpos = dfhack.textures.getTexposByHandle( + notes_textures.green_pin[1] + ) return dfhack.pen.parse{ ch='X', fg=COLOR_BLUE, diff --git a/test/gui/notes.lua b/test/gui/notes.lua index 83013d37ca..270c4fe2cc 100644 --- a/test/gui/notes.lua +++ b/test/gui/notes.lua @@ -3,6 +3,7 @@ local gui_notes = reqscript('gui/notes') local utils = require('utils') local guidm = require('gui.dwarfmode') local overlay = require('plugins.overlay') +local notes_textures = reqscript('notes').textures config = { target = 'gui/notes', @@ -43,6 +44,7 @@ local function arrange_gui_notes(options) gui_notes.main() local gui_notes = gui_notes.view + gui_notes.enable_selector_blink = false gui_notes:updateLayout() gui_notes:onRender() @@ -238,7 +240,6 @@ function test.edit_note() note_manager.subviews.name:setText('updated green note 2') note_manager.subviews.comment:setText('updated comment 2') local screen = dfhack.gui.getCurViewscreen(true) - printall(screen.widgets) gui.simulateInput(dfhack.gui.getCurViewscreen(true), 'CUSTOM_CTRL_ENTER') local note_list = gui_notes.subviews.note_list:getChoices() @@ -281,3 +282,68 @@ function test.delete_note() cleanup(gui_notes) end + +function test.create_new_note() + local notes = { + {name='green note 1', comment='comment 1', pos={x=1, y=1, z=1}}, + } + + local gui_notes, gui_notes_window = arrange_gui_notes({ notes=notes }) + + local note_list = gui_notes.subviews.note_list:getChoices() + expect.eq(#note_list, 1) + + gui.simulateInput(dfhack.gui.getCurViewscreen(true), 'CUSTOM_CTRL_N') + + local viewport = guidm.Viewport.get() + + local half_x = math.floor((viewport.x1 + viewport.x2) / 2) + local half_y = math.floor((viewport.y1 + viewport.y2) / 2) + + local pos = {x=half_x, y=half_y, z=viewport.z} + local screen_pos = viewport:tileToScreen(pos) + df.global.cursor = pos + + -- should not be a test function to map screen tile to mouse pos? + df.global.gps.precise_mouse_x = screen_pos.x * df.global.gps.viewport_zoom_factor / 4 + df.global.gps.precise_mouse_y = screen_pos.y * df.global.gps.viewport_zoom_factor / 4 + + df.global.gps.mouse_x = screen_pos.x + df.global.gps.mouse_y = screen_pos.y + + gui_notes:render(gui.Painter.new()) + + local pen = dfhack.screen.readTile(screen_pos.x, screen_pos.y, true) + + if dfhack.screen.inGraphicsMode() then + local pin_textpos = dfhack.textures.getTexposByHandle( + notes_textures.green_pin[1] + ) + expect.eq(pen and pen.tile, pin_textpos) + else + expect.eq(pen and pen.ch, string.byte('X')) + end + + gui.simulateInput(dfhack.gui.getCurViewscreen(true), '_MOUSE_L') + + local note_manager = gui_notes_window.note_manager + + expect.ne(note_manager, nil) + expect.eq(note_manager.visible, true) + + note_manager.subviews.name:setText('note 2') + note_manager.subviews.comment:setText('new note') + + gui.simulateInput(dfhack.gui.getCurViewscreen(true), 'CUSTOM_CTRL_ENTER') + + local note_list = gui_notes.subviews.note_list:getChoices() + expect.eq(#note_list, 2) + + local gui_note = note_list[2] + expect.eq(gui_note.text, 'note 2') + expect.eq(gui_note.point.comment, 'new note') + expect.table_eq(gui_note.point.pos, pos) + + cleanup(gui_notes) +end + From 3ac3b0e971458a29373e98aa7d4e753a1a35ac3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Obr=C4=99bski?= Date: Sun, 23 Feb 2025 09:16:33 +0100 Subject: [PATCH 07/10] Fix notes overlay tests to work in ASCII mode --- gui/notes.lua | 2 +- test/gui/notes.lua | 6 ++-- test/overlay/notes.lua | 66 +++++++++++++++++++++++++----------------- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/gui/notes.lua b/gui/notes.lua index 242e9aa8cc..4d8eee7d4d 100644 --- a/gui/notes.lua +++ b/gui/notes.lua @@ -76,7 +76,7 @@ function NotesWindow:init() auto_width=true, label='New note', key='CUSTOM_CTRL_N', - visible=edit_mode, + visible=true, on_activate=function() if self.on_note_add then self:on_note_add() diff --git a/test/gui/notes.lua b/test/gui/notes.lua index 270c4fe2cc..992e812ddd 100644 --- a/test/gui/notes.lua +++ b/test/gui/notes.lua @@ -324,7 +324,10 @@ function test.create_new_note() expect.eq(pen and pen.ch, string.byte('X')) end - gui.simulateInput(dfhack.gui.getCurViewscreen(true), '_MOUSE_L') + gui.simulateInput(dfhack.gui.getCurViewscreen(true), { + _MOUSE_L=true, + _MOUSE_L_DOWN=true, + }) local note_manager = gui_notes_window.note_manager @@ -346,4 +349,3 @@ function test.create_new_note() cleanup(gui_notes) end - diff --git a/test/overlay/notes.lua b/test/overlay/notes.lua index b096f30399..c648cebf29 100644 --- a/test/overlay/notes.lua +++ b/test/overlay/notes.lua @@ -22,7 +22,7 @@ local function install_notes_overlay(options) overlay.rescan() overlay.overlay_command({'enable', 'notes.map_notes'}) - -- if overlay + local overlay_state = overlay.get_state() if not overlay_state.config['notes.map_notes'].enabled then qerror('can not enable notes.map_notes overlay') @@ -62,6 +62,27 @@ local function add_note(notes_overlay, pos, name, comment) gui.simulateInput(dfhack.gui.getCurViewscreen(true), 'CUSTOM_CTRL_ENTER') end +function assert_note_pen(pen) + if dfhack.screen.inGraphicsMode() then + local pin_textpos = dfhack.textures.getTexposByHandle( + notes_textures.green_pin[1] + ) + expect.eq(pen and pen.tile, pin_textpos) + else + expect.eq(pen and pen.ch, string.byte('N')) + end +end + +function set_mouse_screen_pos(screen_pos) + -- should not be a test function to map screen tile to mouse pos? + df.global.gps.precise_mouse_x = screen_pos.x * df.global.gps.viewport_zoom_factor / 4 + df.global.gps.precise_mouse_y = screen_pos.y * df.global.gps.viewport_zoom_factor / 4 + + df.global.gps.mouse_x = screen_pos.x + df.global.gps.mouse_y = screen_pos.y + +end + function test.load_notes_overlay() local notes_overlay = install_notes_overlay() expect.ne(notes_overlay, nil) @@ -90,9 +111,9 @@ function test.render_existing_notes() local half_x = math.floor((viewport.x1 + viewport.x2) / 2) local half_y = math.floor((viewport.y1 + viewport.y2) / 2) - local pos_1 = {x=half_x, y=viewport.y1, z=viewport.z} - local pos_2 = {x=viewport.x1, y=half_y, z=viewport.z} - local pos_3 = {x=half_x, y=half_y, z=viewport.z} + local pos_1 = {x=half_x, y=half_y, z=viewport.z} + local pos_2 = {x=half_x - 2, y=half_y + 2, z=viewport.z} + local pos_3 = {x=half_x + 2, y=half_y + 2, z=viewport.z} add_note(notes_overlay, pos_1, 'note 1', 'first note') add_note(notes_overlay, pos_2, 'note 2', 'second note') @@ -100,16 +121,12 @@ function test.render_existing_notes() reload_notes() - local pin_textpos = dfhack.textures.getTexposByHandle( - notes_textures.green_pin[1] - ) - for _, pos in ipairs({pos_1, pos_2, pos_3}) do notes_overlay:render(gui.Painter.new()) local screen_pos = viewport:tileToScreen(pos) local pen = dfhack.screen.readTile(screen_pos.x, screen_pos.y, true) - expect.eq(pen and pen.tile, pin_textpos) + assert_note_pen(pen) end cleanup(notes_overlay) @@ -123,9 +140,9 @@ function test.edit_clicked_note() local half_x = math.floor((viewport.x1 + viewport.x2) / 2) local half_y = math.floor((viewport.y1 + viewport.y2) / 2) - local pos_1 = {x=half_x, y=viewport.y1, z=viewport.z} - local pos_2 = {x=viewport.x1, y=half_y, z=viewport.z} - local pos_3 = {x=half_x, y=half_y, z=viewport.z} + local pos_1 = {x=half_x, y=half_y, z=viewport.z} + local pos_2 = {x=half_x - 2, y=half_y + 2, z=viewport.z} + local pos_3 = {x=half_x + 2, y=half_y + 2, z=viewport.z} add_note(notes_overlay, pos_1, 'note 1', 'note to edit') add_note(notes_overlay, pos_2, 'note 2', 'other note') @@ -135,19 +152,16 @@ function test.edit_clicked_note() local screen_pos = viewport:tileToScreen(pos_1) - local rect = gui.ViewRect{rect=notes_overlay.frame_rect} + set_mouse_screen_pos(screen_pos) - -- should not be a test function to map screen tile to mouse pos? - df.global.gps.precise_mouse_x = screen_pos.x * df.global.gps.viewport_zoom_factor / 4 - df.global.gps.precise_mouse_y = screen_pos.y * df.global.gps.viewport_zoom_factor / 4 - - local screen = dfhack.gui.getCurViewscreen(true) - gui.simulateInput(screen, { + gui.simulateInput(dfhack.gui.getCurViewscreen(true), { _MOUSE_L=true, + _MOUSE_L_DOWN=true, }) local note_manager = notes_overlay.note_manager expect.ne(note_manager, nil) + expect.eq(note_manager:isDismissed(), false) expect.eq(note_manager.subviews.name:getText(), 'note 1') expect.eq(note_manager.subviews.comment:getText(), 'note to edit') @@ -171,9 +185,9 @@ function test.delete_clicked_note() local half_x = math.floor((viewport.x1 + viewport.x2) / 2) local half_y = math.floor((viewport.y1 + viewport.y2) / 2) - local pos_1 = {x=half_x, y=viewport.y1, z=viewport.z} - local pos_2 = {x=viewport.x1, y=half_y, z=viewport.z} - local pos_3 = {x=half_x, y=half_y, z=viewport.z} + local pos_1 = {x=half_x, y=half_y, z=viewport.z} + local pos_2 = {x=half_x - 2, y=half_y + 2, z=viewport.z} + local pos_3 = {x=half_x + 2, y=half_y + 2, z=viewport.z} add_note(notes_overlay, pos_1, 'note 1', 'note to edit') add_note(notes_overlay, pos_2, 'note 2', 'other note') @@ -185,13 +199,11 @@ function test.delete_clicked_note() local rect = gui.ViewRect{rect=notes_overlay.frame_rect} - -- should not be a test function to map screen tile to mouse pos? - df.global.gps.precise_mouse_x = screen_pos.x * df.global.gps.viewport_zoom_factor / 4 - df.global.gps.precise_mouse_y = screen_pos.y * df.global.gps.viewport_zoom_factor / 4 + set_mouse_screen_pos(screen_pos) - local screen = dfhack.gui.getCurViewscreen(true) - gui.simulateInput(screen, { + gui.simulateInput(dfhack.gui.getCurViewscreen(true), { _MOUSE_L=true, + _MOUSE_L_DOWN=true, }) expect.eq(#map_points, 3) From 104e02bf65d0153f8d7e7a5ff883719309e3d663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Obr=C4=99bski?= Date: Mon, 24 Feb 2025 07:42:45 +0100 Subject: [PATCH 08/10] Fix notes corner case failed tests Test failed if the cam has been in left-top corner of the map --- test/gui/notes.lua | 18 ++++++++++++++++-- test/overlay/notes.lua | 28 ++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/test/gui/notes.lua b/test/gui/notes.lua index 992e812ddd..9bb1c7ac76 100644 --- a/test/gui/notes.lua +++ b/test/gui/notes.lua @@ -66,6 +66,21 @@ local function cleanup(gui_notes) map_points_backup = nil end +function get_visible_map_center() + local viewport = guidm.Viewport.get() + + local half_x = math.max( + math.floor((viewport.x1 + viewport.x2) / 2), + 2 + ) + local half_y = math.max( + math.floor((viewport.y1 + viewport.y2) / 2), + 2 + ) + + return half_x, half_y, viewport.z +end + function test.load_gui_notes() local gui_notes = arrange_gui_notes() expect.eq(gui_notes.visible, true) @@ -297,8 +312,7 @@ function test.create_new_note() local viewport = guidm.Viewport.get() - local half_x = math.floor((viewport.x1 + viewport.x2) / 2) - local half_y = math.floor((viewport.y1 + viewport.y2) / 2) + local half_x, half_y = get_visible_map_center() local pos = {x=half_x, y=half_y, z=viewport.z} local screen_pos = viewport:tileToScreen(pos) diff --git a/test/overlay/notes.lua b/test/overlay/notes.lua index c648cebf29..c6daa5c65d 100644 --- a/test/overlay/notes.lua +++ b/test/overlay/notes.lua @@ -23,11 +23,11 @@ local function install_notes_overlay(options) overlay.rescan() overlay.overlay_command({'enable', 'notes.map_notes'}) - local overlay_state = overlay.get_state() - if not overlay_state.config['notes.map_notes'].enabled then + if not overlay.isOverlayEnabled('notes.map_notes') then qerror('can not enable notes.map_notes overlay') end + local overlay_state = overlay.get_state() return overlay_state.db['notes.map_notes'].widget end @@ -83,6 +83,21 @@ function set_mouse_screen_pos(screen_pos) end +function get_visible_map_center() + local viewport = guidm.Viewport.get() + + local half_x = math.max( + math.floor((viewport.x1 + viewport.x2) / 2), + 2 + ) + local half_y = math.max( + math.floor((viewport.y1 + viewport.y2) / 2), + 2 + ) + + return half_x, half_y, viewport.z +end + function test.load_notes_overlay() local notes_overlay = install_notes_overlay() expect.ne(notes_overlay, nil) @@ -108,8 +123,7 @@ function test.render_existing_notes() local viewport = guidm.Viewport.get() - local half_x = math.floor((viewport.x1 + viewport.x2) / 2) - local half_y = math.floor((viewport.y1 + viewport.y2) / 2) + local half_x, half_y = get_visible_map_center() local pos_1 = {x=half_x, y=half_y, z=viewport.z} local pos_2 = {x=half_x - 2, y=half_y + 2, z=viewport.z} @@ -137,8 +151,7 @@ function test.edit_clicked_note() local viewport = guidm.Viewport.get() - local half_x = math.floor((viewport.x1 + viewport.x2) / 2) - local half_y = math.floor((viewport.y1 + viewport.y2) / 2) + local half_x, half_y, z = get_visible_map_center() local pos_1 = {x=half_x, y=half_y, z=viewport.z} local pos_2 = {x=half_x - 2, y=half_y + 2, z=viewport.z} @@ -182,8 +195,7 @@ function test.delete_clicked_note() local viewport = guidm.Viewport.get() - local half_x = math.floor((viewport.x1 + viewport.x2) / 2) - local half_y = math.floor((viewport.y1 + viewport.y2) / 2) + local half_x, half_y = get_visible_map_center() local pos_1 = {x=half_x, y=half_y, z=viewport.z} local pos_2 = {x=half_x - 2, y=half_y + 2, z=viewport.z} From 622fb2d8d1e149e8ee983eccbeabee97cb2998ff Mon Sep 17 00:00:00 2001 From: Wiktor Obrebski Date: Thu, 27 Feb 2025 19:55:59 +0100 Subject: [PATCH 09/10] Fix notes overlay test --- test/overlay/notes.lua | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/test/overlay/notes.lua b/test/overlay/notes.lua index c6daa5c65d..e1b7a56889 100644 --- a/test/overlay/notes.lua +++ b/test/overlay/notes.lua @@ -28,6 +28,7 @@ local function install_notes_overlay(options) end local overlay_state = overlay.get_state() + return overlay_state.db['notes.map_notes'].widget end @@ -86,16 +87,24 @@ end function get_visible_map_center() local viewport = guidm.Viewport.get() - local half_x = math.max( - math.floor((viewport.x1 + viewport.x2) / 2), - 2 + local map_width, map_height = dfhack.maps.getTileSize() + local world_rect = gui.mkdims_wh(0, 0, map_width, map_height) + -- find center of visible part of the map + local map_rect = gui.ViewRect{rect=world_rect}:viewport(viewport) + + local half_x = math.floor((map_rect.clip_x1 + map_rect.clip_x2) / 2) + local normalized_half_x = math.min( + math.max(half_x, map_rect.clip_x1), + map_rect.clip_x2 ) - local half_y = math.max( - math.floor((viewport.y1 + viewport.y2) / 2), - 2 + + local half_y = math.floor((map_rect.clip_y1 + map_rect.clip_y2) / 2) + local normalized_half_y = math.min( + math.max(half_y, map_rect.clip_y1), + map_rect.clip_y2 ) - return half_x, half_y, viewport.z + return normalized_half_x, normalized_half_y, viewport.z end function test.load_notes_overlay() From da68893d1cf544f2087d550429ad1236aa6e3ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Obr=C4=99bski?= Date: Sat, 1 Mar 2025 06:15:56 +0100 Subject: [PATCH 10/10] Fix notes overlay test in case of empty config test suite --- test/overlay/notes.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/overlay/notes.lua b/test/overlay/notes.lua index e1b7a56889..401e02af94 100644 --- a/test/overlay/notes.lua +++ b/test/overlay/notes.lua @@ -13,6 +13,7 @@ config = { } local map_points_backup = nil +local was_overlay_enabled = overlay.isEnabled() local function install_notes_overlay(options) options = options or {} @@ -20,6 +21,9 @@ local function install_notes_overlay(options) map_points_backup = utils.clone(map_points) map_points:resize(0) + local was_overlay_enabled = overlay.isEnabled() + + overlay.setEnabled(true) overlay.rescan() overlay.overlay_command({'enable', 'notes.map_notes'}) @@ -48,6 +52,8 @@ local function cleanup(notes_overlay) map_points_backup = nil reload_notes() + + overlay.setEnabled(was_overlay_enabled) end local function add_note(notes_overlay, pos, name, comment)