Tweak the API for current viewscreen, and dispatch show/dismiss from C++.

develop
Alexander Gavrilov 2012-08-24 13:20:08 +04:00
parent b12b9fa91e
commit e825dc5ddb
10 changed files with 96 additions and 33 deletions

@ -724,15 +724,20 @@ can be omitted.
Gui module Gui module
---------- ----------
* ``dfhack.gui.getCurViewscreen()`` * ``dfhack.gui.getCurViewscreen([skip_dismissed])``
Returns the viewscreen that is current in the core. Returns the topmost viewscreen. If ``skip_dismissed`` is *true*,
ignores screens already marked to be removed.
* ``dfhack.gui.getFocusString(viewscreen)`` * ``dfhack.gui.getFocusString(viewscreen)``
Returns a string representation of the current focus position Returns a string representation of the current focus position
in the ui. The string has a "screen/foo/bar/baz..." format. 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])`` * ``dfhack.gui.getSelectedWorkshopJob([silent])``
When a job is selected in *'q'* mode, returns the job, else When a job is selected in *'q'* mode, returns the job, else
@ -1291,9 +1296,10 @@ Screens are managed with the following functions:
Displays the given screen, possibly placing it below a different one. Displays the given screen, possibly placing it below a different one.
The screen must not be already shown. Returns *true* if success. The screen must not be already shown. Returns *true* if success.
* ``dfhack.screen.dismiss(screen)`` * ``dfhack.screen.dismiss(screen[,to_first])``
Marks the screen to be removed when the game enters its event loop. 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)`` * ``dfhack.screen.isDismissed(screen)``
@ -1312,10 +1318,22 @@ Supported callbacks and fields are:
Initialized by ``show`` with a reference to the backing viewscreen Initialized by ``show`` with a reference to the backing viewscreen
object, and removed again when the object is deleted. 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()`` * ``function screen:onDestroy()``
Called from the destructor when the viewscreen is deleted. 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()`` * ``function screen:onRender()``
Called when the viewscreen should paint itself. This is the only context Called when the viewscreen should paint itself. This is the only context

@ -987,13 +987,17 @@ can be omitted.</p>
<div class="section" id="gui-module"> <div class="section" id="gui-module">
<h3><a class="toc-backref" href="#id18">Gui module</a></h3> <h3><a class="toc-backref" href="#id18">Gui module</a></h3>
<ul> <ul>
<li><p class="first"><tt class="docutils literal">dfhack.gui.getCurViewscreen()</tt></p> <li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.getCurViewscreen([skip_dismissed])</span></tt></p>
<p>Returns the viewscreen that is current in the core.</p> <p>Returns the topmost viewscreen. If <tt class="docutils literal">skip_dismissed</tt> is <em>true</em>,
ignores screens already marked to be removed.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.gui.getFocusString(viewscreen)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.gui.getFocusString(viewscreen)</tt></p>
<p>Returns a string representation of the current focus position <p>Returns a string representation of the current focus position
in the ui. The string has a &quot;screen/foo/bar/baz...&quot; format.</p> in the ui. The string has a &quot;screen/foo/bar/baz...&quot; format.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.getCurFocus([skip_dismissed])</span></tt></p>
<p>Returns the focus string of the current viewscreen.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.getSelectedWorkshopJob([silent])</span></tt></p> <li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.getSelectedWorkshopJob([silent])</span></tt></p>
<p>When a job is selected in <em>'q'</em> mode, returns the job, else <p>When a job is selected in <em>'q'</em> mode, returns the job, else
prints error unless silent and returns <em>nil</em>.</p> prints error unless silent and returns <em>nil</em>.</p>
@ -1465,8 +1469,9 @@ interface screens added by dfhack should bear the &quot;DFHack&quot; signature.<
<p>Displays the given screen, possibly placing it below a different one. <p>Displays the given screen, possibly placing it below a different one.
The screen must not be already shown. Returns <em>true</em> if success.</p> The screen must not be already shown. Returns <em>true</em> if success.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.screen.dismiss(screen)</tt></p> <li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.screen.dismiss(screen[,to_first])</span></tt></p>
<p>Marks the screen to be removed when the game enters its event loop.</p> <p>Marks the screen to be removed when the game enters its event loop.
If <tt class="docutils literal">to_first</tt> is <em>true</em>, all screens up to the first one will be deleted.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.screen.isDismissed(screen)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.screen.isDismissed(screen)</tt></p>
<p>Checks if the screen is already marked for removal.</p> <p>Checks if the screen is already marked for removal.</p>
@ -1482,9 +1487,18 @@ that delegates all processing to methods stored in that table.</p>
<p>Initialized by <tt class="docutils literal">show</tt> with a reference to the backing viewscreen <p>Initialized by <tt class="docutils literal">show</tt> with a reference to the backing viewscreen
object, and removed again when the object is deleted.</p> object, and removed again when the object is deleted.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">function screen:onShow()</tt></p>
<p>Called by <tt class="docutils literal">dfhack.screen.show</tt> if successful.</p>
</li>
<li><p class="first"><tt class="docutils literal">function screen:onDismiss()</tt></p>
<p>Called by <tt class="docutils literal">dfhack.screen.dismiss</tt> if successful.</p>
</li>
<li><p class="first"><tt class="docutils literal">function screen:onDestroy()</tt></p> <li><p class="first"><tt class="docutils literal">function screen:onDestroy()</tt></p>
<p>Called from the destructor when the viewscreen is deleted.</p> <p>Called from the destructor when the viewscreen is deleted.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">function screen:onResize(w, h)</tt></p>
<p>Called before <tt class="docutils literal">onRender</tt> or <tt class="docutils literal">onIdle</tt> when the window size has changed.</p>
</li>
<li><p class="first"><tt class="docutils literal">function screen:onRender()</tt></p> <li><p class="first"><tt class="docutils literal">function screen:onRender()</tt></p>
<p>Called when the viewscreen should paint itself. This is the only context <p>Called when the viewscreen should paint itself. This is the only context
where the above painting functions work correctly.</p> where the above painting functions work correctly.</p>

@ -1260,7 +1260,7 @@ bool Core::ncurses_wgetch(int in, int & out)
// FIXME: copypasta, push into a method! // FIXME: copypasta, push into a method!
if(df::global::ui && df::global::gview) if(df::global::ui && df::global::gview)
{ {
df::viewscreen * ws = Gui::GetCurrentScreen(); df::viewscreen * ws = Gui::getCurViewscreen();
if (strict_virtual_cast<df::viewscreen_dwarfmodest>(ws) && if (strict_virtual_cast<df::viewscreen_dwarfmodest>(ws) &&
df::global::ui->main.mode != ui_sidebar_mode::Hotkeys && df::global::ui->main.mode != ui_sidebar_mode::Hotkeys &&
df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None) df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)

@ -749,6 +749,7 @@ static const LuaWrapper::FunctionReg dfhack_module[] = {
static const LuaWrapper::FunctionReg dfhack_gui_module[] = { static const LuaWrapper::FunctionReg dfhack_gui_module[] = {
WRAPM(Gui, getCurViewscreen), WRAPM(Gui, getCurViewscreen),
WRAPM(Gui, getFocusString), WRAPM(Gui, getFocusString),
WRAPM(Gui, getCurFocus),
WRAPM(Gui, getSelectedWorkshopJob), WRAPM(Gui, getSelectedWorkshopJob),
WRAPM(Gui, getSelectedJob), WRAPM(Gui, getSelectedJob),
WRAPM(Gui, getSelectedUnit), WRAPM(Gui, getSelectedUnit),

@ -55,8 +55,6 @@ namespace DFHack
*/ */
namespace Gui namespace Gui
{ {
inline df::viewscreen *getCurViewscreen() { return Core::getTopViewscreen(); }
DFHACK_EXPORT std::string getFocusString(df::viewscreen *top); DFHACK_EXPORT std::string getFocusString(df::viewscreen *top);
// Full-screen item details view // Full-screen item details view
@ -113,7 +111,11 @@ namespace DFHack
* Gui screens * Gui screens
*/ */
/// Get the current top-level view-screen /// 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 /// get the size of the window buffer
DFHACK_EXPORT bool getWindowSize(int32_t & width, int32_t & height); DFHACK_EXPORT bool getWindowSize(int32_t & width, int32_t & height);

@ -112,7 +112,7 @@ namespace DFHack
// Push and remove viewscreens // Push and remove viewscreens
DFHACK_EXPORT bool show(df::viewscreen *screen, df::viewscreen *before = NULL); 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); DFHACK_EXPORT bool isDismissed(df::viewscreen *screen);
} }
@ -136,7 +136,10 @@ namespace DFHack
virtual bool key_conflict(df::interface_key key); virtual bool key_conflict(df::interface_key key);
virtual bool is_lua_screen() { return false; } virtual bool is_lua_screen() { return false; }
virtual std::string getFocusString() = 0; virtual std::string getFocusString() = 0;
virtual void onShow() {};
virtual void onDismiss() {};
}; };
class DFHACK_EXPORT dfhack_lua_viewscreen : public dfhack_viewscreen { class DFHACK_EXPORT dfhack_lua_viewscreen : public dfhack_viewscreen {
@ -166,5 +169,8 @@ namespace DFHack
virtual void help(); virtual void help();
virtual void resize(int w, int h); virtual void resize(int w, int h);
virtual void feed(std::set<df::interface_key> *keys); virtual void feed(std::set<df::interface_key> *keys);
virtual void onShow();
virtual void onDismiss();
}; };
} }

@ -232,9 +232,7 @@ function Screen:show(below)
error("This screen is already on display") error("This screen is already on display")
end end
self:onAboutToShow(below) self:onAboutToShow(below)
if dscreen.show(self, below) then if not dscreen.show(self, below) then
self:onShown()
else
error('Could not show screen') error('Could not show screen')
end end
end end
@ -242,17 +240,16 @@ end
function Screen:onAboutToShow() function Screen:onAboutToShow()
end end
function Screen:onShown() function Screen:onShow()
end end
function Screen:dismiss() function Screen:dismiss()
if self._native and not dscreen.isDismissed(self) then if self._native then
dscreen.dismiss(self) dscreen.dismiss(self)
self:onDismissed()
end end
end end
function Screen:onDismissed() function Screen:onDismiss()
end end
------------------------ ------------------------

@ -983,17 +983,19 @@ void Gui::showPopupAnnouncement(std::string message, int color, bool bright)
world->status.popups.push_back(popup); world->status.popups.push_back(popup);
} }
df::viewscreen * Gui::GetCurrentScreen() df::viewscreen *Gui::getCurViewscreen(bool skip_dismissed)
{ {
df::viewscreen * ws = &gview->view; df::viewscreen * ws = &gview->view;
while(ws) while (ws && ws->child)
{
if(ws->child)
ws = ws->child; ws = ws->child;
else
return ws; if (skip_dismissed)
{
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) bool Gui::getViewCoords (int32_t &x, int32_t &y, int32_t &z)

@ -235,14 +235,26 @@ bool Screen::show(df::viewscreen *screen, df::viewscreen *before)
if (screen->child) if (screen->child)
screen->child->parent = screen; screen->child->parent = screen;
if (dfhack_viewscreen::is_instance(screen))
static_cast<dfhack_viewscreen*>(screen)->onShow();
return true; return true;
} }
void Screen::dismiss(df::viewscreen *screen) void Screen::dismiss(df::viewscreen *screen, bool to_first)
{ {
CHECK_NULL_POINTER(screen); CHECK_NULL_POINTER(screen);
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; screen->breakdown_level = interface_breakdown_types::STOPSCREEN;
if (dfhack_viewscreen::is_instance(screen))
static_cast<dfhack_viewscreen*>(screen)->onDismiss();
} }
bool Screen::isDismissed(df::viewscreen *screen) bool Screen::isDismissed(df::viewscreen *screen)
@ -261,6 +273,8 @@ static std::set<df::viewscreen*> dfhack_screens;
dfhack_viewscreen::dfhack_viewscreen() : text_input_mode(false) dfhack_viewscreen::dfhack_viewscreen() : text_input_mode(false)
{ {
dfhack_screens.insert(this); dfhack_screens.insert(this);
last_size = Screen::getWindowSize();
} }
dfhack_viewscreen::~dfhack_viewscreen() dfhack_viewscreen::~dfhack_viewscreen()
@ -576,3 +590,15 @@ void dfhack_lua_viewscreen::feed(std::set<df::interface_key> *keys)
lua_pushlightuserdata(Lua::Core::State, keys); lua_pushlightuserdata(Lua::Core::State, keys);
safe_call_lua(do_input, 1, 0); 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);
}

@ -142,11 +142,8 @@ function MechanismList:onInput(keys)
end end
end end
if not df.viewscreen_dwarfmodest:is_instance(dfhack.gui.getCurViewscreen()) then if dfhack.gui.getCurFocus() ~= 'dwarfmode/QueryBuilding/Some' then
qerror("This script requires the main dwarfmode view") qerror("This script requires the main dwarfmode view in 'q' mode")
end
if df.global.ui.main.mode ~= df.ui_sidebar_mode.QueryBuilding then
qerror("This script requires the 'q' interface mode")
end end
local list = MechanismList.new(df.global.world.selected_building) local list = MechanismList.new(df.global.world.selected_building)