-dfhack.gui.getCurViewscreen()
-Returns the viewscreen that is current in the core.
+dfhack.gui.getCurViewscreen([skip_dismissed])
+Returns the topmost viewscreen. If skip_dismissed is true,
+ignores screens already marked to be removed.
dfhack.gui.getFocusString(viewscreen)
Returns a string representation of the current focus position
in the ui. The string has a "screen/foo/bar/baz..." format.
+dfhack.gui.getCurFocus([skip_dismissed])
+Returns the focus string of the current viewscreen.
+
dfhack.gui.getSelectedWorkshopJob([silent])
When a job is selected in 'q' mode, returns the job, else
prints error unless silent and returns nil.
@@ -1465,8 +1469,9 @@ interface screens added by dfhack should bear the "DFHack" signature.<
Displays the given screen, possibly placing it below a different one.
The screen must not be already shown. Returns true if success.
-dfhack.screen.dismiss(screen)
-Marks the screen to be removed when the game enters its event loop.
+dfhack.screen.dismiss(screen[,to_first])
+Marks the screen to be removed when the game enters its event loop.
+If to_first is true, all screens up to the first one will be deleted.
dfhack.screen.isDismissed(screen)
Checks if the screen is already marked for removal.
@@ -1482,9 +1487,18 @@ that delegates all processing to methods stored in that table.
Initialized by show with a reference to the backing viewscreen
object, and removed again when the object is deleted.
+function screen:onShow()
+Called by dfhack.screen.show if successful.
+
+function screen:onDismiss()
+Called by dfhack.screen.dismiss if successful.
+
function screen:onDestroy()
Called from the destructor when the viewscreen is deleted.
+function screen:onResize(w, h)
+Called before onRender or onIdle when the window size has changed.
+
function screen:onRender()
Called when the viewscreen should paint itself. This is the only context
where the above painting functions work correctly.
diff --git a/library/Core.cpp b/library/Core.cpp
index a61fef4e9..6a0dea7c2 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -1260,7 +1260,7 @@ bool Core::ncurses_wgetch(int in, int & out)
// FIXME: copypasta, push into a method!
if(df::global::ui && df::global::gview)
{
- df::viewscreen * ws = Gui::GetCurrentScreen();
+ df::viewscreen * ws = Gui::getCurViewscreen();
if (strict_virtual_cast(ws) &&
df::global::ui->main.mode != ui_sidebar_mode::Hotkeys &&
df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index d25da8087..35cf1435b 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -749,6 +749,7 @@ static const LuaWrapper::FunctionReg dfhack_module[] = {
static const LuaWrapper::FunctionReg dfhack_gui_module[] = {
WRAPM(Gui, getCurViewscreen),
WRAPM(Gui, getFocusString),
+ WRAPM(Gui, getCurFocus),
WRAPM(Gui, getSelectedWorkshopJob),
WRAPM(Gui, getSelectedJob),
WRAPM(Gui, getSelectedUnit),
diff --git a/library/include/modules/Gui.h b/library/include/modules/Gui.h
index e7155c436..273d84cee 100644
--- a/library/include/modules/Gui.h
+++ b/library/include/modules/Gui.h
@@ -55,8 +55,6 @@ namespace DFHack
*/
namespace Gui
{
- inline df::viewscreen *getCurViewscreen() { return Core::getTopViewscreen(); }
-
DFHACK_EXPORT std::string getFocusString(df::viewscreen *top);
// Full-screen item details view
@@ -113,7 +111,11 @@ namespace DFHack
* Gui screens
*/
/// Get the current top-level view-screen
- DFHACK_EXPORT df::viewscreen * GetCurrentScreen();
+ DFHACK_EXPORT df::viewscreen *getCurViewscreen(bool skip_dismissed = false);
+
+ inline std::string getCurFocus(bool skip_dismissed = false) {
+ return getFocusString(getCurViewscreen(skip_dismissed));
+ }
/// get the size of the window buffer
DFHACK_EXPORT bool getWindowSize(int32_t & width, int32_t & height);
diff --git a/library/include/modules/Screen.h b/library/include/modules/Screen.h
index ce3f32ed2..492e1eecc 100644
--- a/library/include/modules/Screen.h
+++ b/library/include/modules/Screen.h
@@ -112,7 +112,7 @@ namespace DFHack
// Push and remove viewscreens
DFHACK_EXPORT bool show(df::viewscreen *screen, df::viewscreen *before = NULL);
- DFHACK_EXPORT void dismiss(df::viewscreen *screen);
+ DFHACK_EXPORT void dismiss(df::viewscreen *screen, bool to_first = false);
DFHACK_EXPORT bool isDismissed(df::viewscreen *screen);
}
@@ -136,7 +136,10 @@ namespace DFHack
virtual bool key_conflict(df::interface_key key);
virtual bool is_lua_screen() { return false; }
+
virtual std::string getFocusString() = 0;
+ virtual void onShow() {};
+ virtual void onDismiss() {};
};
class DFHACK_EXPORT dfhack_lua_viewscreen : public dfhack_viewscreen {
@@ -166,5 +169,8 @@ namespace DFHack
virtual void help();
virtual void resize(int w, int h);
virtual void feed(std::set *keys);
+
+ virtual void onShow();
+ virtual void onDismiss();
};
}
diff --git a/library/lua/gui.lua b/library/lua/gui.lua
index f9a45548f..62e393f0b 100644
--- a/library/lua/gui.lua
+++ b/library/lua/gui.lua
@@ -232,9 +232,7 @@ function Screen:show(below)
error("This screen is already on display")
end
self:onAboutToShow(below)
- if dscreen.show(self, below) then
- self:onShown()
- else
+ if not dscreen.show(self, below) then
error('Could not show screen')
end
end
@@ -242,17 +240,16 @@ end
function Screen:onAboutToShow()
end
-function Screen:onShown()
+function Screen:onShow()
end
function Screen:dismiss()
- if self._native and not dscreen.isDismissed(self) then
+ if self._native then
dscreen.dismiss(self)
- self:onDismissed()
end
end
-function Screen:onDismissed()
+function Screen:onDismiss()
end
------------------------
diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp
index 9d3ee96eb..91a17e998 100644
--- a/library/modules/Gui.cpp
+++ b/library/modules/Gui.cpp
@@ -983,17 +983,19 @@ void Gui::showPopupAnnouncement(std::string message, int color, bool bright)
world->status.popups.push_back(popup);
}
-df::viewscreen * Gui::GetCurrentScreen()
+df::viewscreen *Gui::getCurViewscreen(bool skip_dismissed)
{
df::viewscreen * ws = &gview->view;
- while(ws)
+ while (ws && ws->child)
+ ws = ws->child;
+
+ if (skip_dismissed)
{
- if(ws->child)
- ws = ws->child;
- else
- return ws;
+ while (ws && Screen::isDismissed(ws) && ws->parent)
+ ws = ws->parent;
}
- return 0;
+
+ return ws;
}
bool Gui::getViewCoords (int32_t &x, int32_t &y, int32_t &z)
diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp
index 9b6839a40..c2377f2ca 100644
--- a/library/modules/Screen.cpp
+++ b/library/modules/Screen.cpp
@@ -235,14 +235,26 @@ bool Screen::show(df::viewscreen *screen, df::viewscreen *before)
if (screen->child)
screen->child->parent = screen;
+ if (dfhack_viewscreen::is_instance(screen))
+ static_cast(screen)->onShow();
+
return true;
}
-void Screen::dismiss(df::viewscreen *screen)
+void Screen::dismiss(df::viewscreen *screen, bool to_first)
{
CHECK_NULL_POINTER(screen);
- screen->breakdown_level = interface_breakdown_types::STOPSCREEN;
+ if (screen->breakdown_level != interface_breakdown_types::NONE)
+ return;
+
+ if (to_first)
+ screen->breakdown_level = interface_breakdown_types::TOFIRST;
+ else
+ screen->breakdown_level = interface_breakdown_types::STOPSCREEN;
+
+ if (dfhack_viewscreen::is_instance(screen))
+ static_cast(screen)->onDismiss();
}
bool Screen::isDismissed(df::viewscreen *screen)
@@ -261,6 +273,8 @@ static std::set dfhack_screens;
dfhack_viewscreen::dfhack_viewscreen() : text_input_mode(false)
{
dfhack_screens.insert(this);
+
+ last_size = Screen::getWindowSize();
}
dfhack_viewscreen::~dfhack_viewscreen()
@@ -576,3 +590,15 @@ void dfhack_lua_viewscreen::feed(std::set *keys)
lua_pushlightuserdata(Lua::Core::State, keys);
safe_call_lua(do_input, 1, 0);
}
+
+void dfhack_lua_viewscreen::onShow()
+{
+ lua_pushstring(Lua::Core::State, "onShow");
+ safe_call_lua(do_notify, 1, 0);
+}
+
+void dfhack_lua_viewscreen::onDismiss()
+{
+ lua_pushstring(Lua::Core::State, "onDismiss");
+ safe_call_lua(do_notify, 1, 0);
+}
diff --git a/scripts/gui/mechanisms.lua b/scripts/gui/mechanisms.lua
index fe45d4acd..3b40ffbd7 100644
--- a/scripts/gui/mechanisms.lua
+++ b/scripts/gui/mechanisms.lua
@@ -142,11 +142,8 @@ function MechanismList:onInput(keys)
end
end
-if not df.viewscreen_dwarfmodest:is_instance(dfhack.gui.getCurViewscreen()) then
- qerror("This script requires the main dwarfmode view")
-end
-if df.global.ui.main.mode ~= df.ui_sidebar_mode.QueryBuilding then
- qerror("This script requires the 'q' interface mode")
+if dfhack.gui.getCurFocus() ~= 'dwarfmode/QueryBuilding/Some' then
+ qerror("This script requires the main dwarfmode view in 'q' mode")
end
local list = MechanismList.new(df.global.world.selected_building)