From cacb082416667ec4309d85e934068ded041d21b8 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 19 Aug 2012 17:53:25 +0400 Subject: [PATCH] Add a stupid example of a lua-controlled viewscreen. --- library/LuaApi.cpp | 10 +++++- library/lua/dfhack.lua | 17 ++++++++++ library/lua/gui.lua | 63 ++++++++++++++++++++++++++++++++++++ library/modules/Screen.cpp | 3 ++ scripts/devel/viewscreen.lua | 18 +++++++++++ 5 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 library/lua/gui.lua create mode 100644 scripts/devel/viewscreen.lua diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index d296a2e55..0f3ed9357 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -196,7 +196,15 @@ static bool get_int_field(lua_State *L, T *pf, int idx, const char *name, int de static void decode_pen(lua_State *L, Pen &pen, int idx) { - get_int_field(L, &pen.ch, idx, "ch", 0); + idx = lua_absindex(L, idx); + + lua_getfield(L, idx, "ch"); + if (lua_isstring(L, -1)) + pen.ch = lua_tostring(L, -1)[0]; + else + get_int_field(L, &pen.ch, idx, "ch", 0); + lua_pop(L, 1); + get_int_field(L, &pen.fg, idx, "fg", 7); get_int_field(L, &pen.bg, idx, "bg", 0); diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index 8c8a75aae..5ebc9809c 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -102,6 +102,23 @@ function reload(module) dofile(path) end +-- Trivial classes + +function defclass(class,parent) + class = class or {} + rawset(class, '__index', rawget(class, '__index') or class) + if parent then + setmetatable(class, parent) + end + return class +end + +function mkinstance(class,table) + table = table or {} + setmetatable(table, class) + return table +end + -- Misc functions function printall(table) diff --git a/library/lua/gui.lua b/library/lua/gui.lua new file mode 100644 index 000000000..0e4e4cc6e --- /dev/null +++ b/library/lua/gui.lua @@ -0,0 +1,63 @@ +-- Viewscreen implementation utility collection. + +local _ENV = mkmodule('gui') + +local dscreen = dfhack.screen + +Screen = defclass(Screen, dfhack.screen) + +function Screen.new(attrs) + return mkinstance(Screen, attrs) +end + +function Screen:isShown() + return self._native ~= nil +end + +function Screen:isActive() + return self:isShown() and not self:isDismissed() +end + +function Screen:renderParent() + if self._native and self._native.parent then + self._native.parent:render() + else + dscreen.clear() + end +end + +function paint_border(x1,y1,x2,y2,color,title) + local pen = { ch = ' ', fg = COLOR_BLACK, bg = color } + dscreen.fillRect(pen,x1,y1,x2,y1) + dscreen.fillRect(pen,x1,y2,x2,y2) + dscreen.fillRect(pen,x1,y1+1,x1,y2-1) + dscreen.fillRect(pen,x2,y1+1,x2,y2-1) + + if title then + local x = math.floor((x2-x1-3-#title)/2 + x1) + pen.bg = bit32.bxor(pen.bg, 8) + dscreen.paintString(pen, x, y1, ' '..title..' ') + end +end + +function Screen:renderFrame(color,title,width,height) + local sw, sh = dscreen.getWindowSize() + local iw, ih = sw-2, sh-2 + width = math.min(width or iw, iw) + height = math.min(height or ih, ih) + local gw, gh = iw-width, ih-height + local x1, y1 = math.floor(gw/2), math.floor(gh/2) + local x2, y2 = x1+width+1, y1+height+1 + + if gw == 0 and gh == 0 then + dscreen.clear() + else + self:renderParent() + dscreen.fillRect({ch=' ',fg=0,bg=0},x1,y1,x2,y2) + end + + paint_border(x1,y1,x2,y2,color,title) + return x1+1,y1+1,width,height,x2-1,y2-1 +end + +return _ENV diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index ac45bb864..ba0313e2d 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -318,6 +318,9 @@ int dfhack_lua_viewscreen::do_destroy(lua_State *L) lua_setfield(L, -2, "_native"); lua_getfield(L, -1, "onDestroy"); + if (lua_isnil(L, -1)) + return 0; + lua_pushvalue(L, -2); lua_call(L, 1, 0); return 0; diff --git a/scripts/devel/viewscreen.lua b/scripts/devel/viewscreen.lua new file mode 100644 index 000000000..c516a7313 --- /dev/null +++ b/scripts/devel/viewscreen.lua @@ -0,0 +1,18 @@ +-- Test lua viewscreens. + +local gui = require 'gui' + +local screen = gui.Screen.new({ + onRender = function(self) + local text = 'Woohoo, lua viewscreen :)' + local x,y,w,h = self:renderFrame(COLOR_GREY,'Hello World',#text+6,3) + self.paintString({fg=COLOR_LIGHTGREEN},x+3,y+1,text) + end, + onInput = function(self,keys) + if keys and (keys.LEAVESCREEN or keys.SELECT) then + self:dismiss() + end + end +}) + +screen:show()