diff --git a/docs/Lua API.rst b/docs/Lua API.rst index a333d9fa0..9ac64fd7c 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -3578,7 +3578,10 @@ It adds the following methods: Adds the screen to the display stack with the given screen as the parent; if parent is not specified, places this one one topmost. Before calling - ``dfhack.screen.show``, calls ``self:onAboutToShow(parent)``. + ``dfhack.screen.show``, calls ``self:onAboutToShow(parent)``. Note that + ``onAboutToShow()`` can dismiss active screens, and therefore change the + potential parent. If parent is not specified, this function will re-detect the + current topmost window after ``self:onAboutToShow(parent)`` returns. * ``screen:onAboutToShow(parent)`` *(for overriding)* diff --git a/docs/changelog.txt b/docs/changelog.txt index deb15d478..b44bb3e0b 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -73,6 +73,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - ``widgets.FilteredList`` now allows all punctuation to be typed into the filter and can match search keys that start with punctuation. - ``widgets.ListBox``: minimum height of dialog is now calculated correctly when there are no items in the list (e.g. when a filter doesn't match anything) - Lua wrappers for functions reverse-engineered from ambushing unit code: ``isHidden(unit)``, ``isFortControlled(unit)``, ``getOuterContainerRef(unit)``, ``getOuterContainerRef(item)`` +- ``dwarfmode.MenuOverlay``: if ``sidebar_mode`` attribute is set, automatically manage entering a specific sidebar mode on show and restoring the previous sidebar mode on dismiss - ``dwarfmode.enterSidebarMode()``: passing ``df.ui_sidebar_mode.DesignateMine`` now always results in you entering ``DesignateMine`` mode and not ``DesignateChopTrees``, even when you looking at the surface where the default designation mode is ``DesignateChopTrees`` - New string class function: ``string:escape_pattern()`` escapes regex special characters within a string - ``widgets.Panel``: if ``autoarrange_subviews`` is set, ``Panel``\s will now automatically lay out widgets vertically according to their current height. This allows you to have widgets dynamically change height or become visible/hidden and you don't have to worry about recalculating frame layouts diff --git a/library/lua/gui.lua b/library/lua/gui.lua index da82f0543..187d558e5 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -537,8 +537,11 @@ function Screen:show(parent) if self._native then error("This screen is already on display") end + self:onAboutToShow(parent or dfhack.gui.getCurViewscreen(true)) + + -- if we're autodetecting the parent, refresh the parent handle in case the + -- original parent has been dismissed by onAboutToShow()'s actions parent = parent or dfhack.gui.getCurViewscreen(true) - self:onAboutToShow(parent) if not dscreen.show(self, parent.child) then error('Could not show screen') end diff --git a/library/lua/gui/dwarfmode.lua b/library/lua/gui/dwarfmode.lua index 65caccc01..b79f7a9b7 100644 --- a/library/lua/gui/dwarfmode.lua +++ b/library/lua/gui/dwarfmode.lua @@ -436,14 +436,41 @@ MenuOverlay = defclass(MenuOverlay, DwarfOverlay) MenuOverlay.ATTRS { frame_inset = 0, frame_background = gui.CLEAR_PEN, + + -- if sidebar_mode is set, we will enter the specified sidebar mode on show + -- and restore the previous sidebar mode on dismiss. otherwise it is up to + -- the caller to ensure we are in a sidebar mode where the menu is visible. + sidebar_mode = DEFAULT_NIL, } function MenuOverlay:computeFrame(parent_rect) return self.df_layout.menu, gui.inset_frame(self.df_layout.menu, self.frame_inset) end -function MenuOverlay:onAboutToShow(below) - MenuOverlay.super.onAboutToShow(self,below) +function MenuOverlay:onAboutToShow(parent) + if not dfhack.isMapLoaded() then + -- sidebar menus are only valid when a fort map is loaded + error('A fortress map must be loaded.') + end + + if self.sidebar_mode then + self.saved_sidebar_mode = df.global.ui.main.mode + -- what mode should we restore when this window is dismissed? ideally, we'd + -- restore the mode that the user has set, but we should fall back to + -- restoring the default mode if either of the following conditions are + -- true: + -- 1) enterSidebarMode doesn't support getting back into the current mode + -- 2) a dfhack viewscreen is currently visible. in this case, we can't trust + -- that the current sidebar mode was set by the user. it could just be a + -- MenuOverlay subclass that is currently being shown that has set the + -- sidebar mode for its own purposes. + if not SIDEBAR_MODE_KEYS[self.saved_sidebar_mode] + or dfhack.gui.getCurFocus(true):find('^dfhack/') then + self.saved_sidebar_mode = df.ui_sidebar_mode.Default + end + + enterSidebarMode(self.sidebar_mode) + end self:updateLayout() if not self.df_layout.menu then @@ -451,6 +478,12 @@ function MenuOverlay:onAboutToShow(below) end end +function MenuOverlay:onDismiss() + if self.saved_sidebar_mode then + enterSidebarMode(self.saved_sidebar_mode) + end +end + function MenuOverlay:render(dc) self:renderParent()