Add a native pen object for lua with a more checked behavior.

develop
Alexander Gavrilov 2012-11-03 20:06:33 +04:00
parent d6f1bb93b5
commit 9598316855
7 changed files with 466 additions and 115 deletions

@ -1555,37 +1555,12 @@ be feasibly used in the core context.</p>
<p>Checks if [GRAPHICS:YES] was specified in init.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.screen.paintTile(pen,x,y[,char,tile])</span></tt></p>
<p>Paints a tile using given parameters. Pen is a table with following possible fields:</p>
<dl class="docutils">
<dt><tt class="docutils literal">ch</tt></dt>
<dd><p class="first last">Provides the ordinary tile character, as either a 1-character string or a number.
Can be overridden with the <tt class="docutils literal">char</tt> function parameter.</p>
</dd>
<dt><tt class="docutils literal">fg</tt></dt>
<dd><p class="first last">Foreground color for the ordinary tile. Defaults to COLOR_GREY (7).</p>
</dd>
<dt><tt class="docutils literal">bg</tt></dt>
<dd><p class="first last">Background color for the ordinary tile. Defaults to COLOR_BLACK (0).</p>
</dd>
<dt><tt class="docutils literal">bold</tt></dt>
<dd><p class="first last">Bright/bold text flag. If <em>nil</em>, computed based on (fg &amp; 8); fg is masked to 3 bits.
Otherwise should be <em>true/false</em>.</p>
</dd>
<dt><tt class="docutils literal">tile</tt></dt>
<dd><p class="first last">Graphical tile id. Ignored unless [GRAPHICS:YES] was in init.txt.</p>
</dd>
<dt><tt class="docutils literal">tile_color = true</tt></dt>
<dd><p class="first last">Specifies that the tile should be shaded with <em>fg/bg</em>.</p>
</dd>
<dt><tt class="docutils literal">tile_fg, tile_bg</tt></dt>
<dd><p class="first last">If specified, overrides <em>tile_color</em> and supplies shading colors directly.</p>
</dd>
</dl>
<p>Paints a tile using given parameters. See below for a description of pen.</p>
<p>Returns <em>false</em> if coordinates out of bounds, or other error.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.screen.readTile(x,y)</tt></p>
<p>Retrieves the contents of the specified tile from the screen buffers.
Returns a pen, or <em>nil</em> if invalid or TrueType.</p>
Returns a pen object, or <em>nil</em> if invalid or TrueType.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.screen.paintString(pen,x,y,text)</tt></p>
<p>Paints the string starting at <em>x,y</em>. Uses the string characters
@ -1610,6 +1585,59 @@ The values can then be used for the <em>tile</em> field of <em>pen</em> structur
functions in this section, this may be used at any time.</p>
</li>
</ul>
<p>The &quot;pen&quot; argument used by functions above may be represented by
a table with the following possible fields:</p>
<blockquote>
<dl class="docutils">
<dt><tt class="docutils literal">ch</tt></dt>
<dd>Provides the ordinary tile character, as either a 1-character string or a number.
Can be overridden with the <tt class="docutils literal">char</tt> function parameter.</dd>
<dt><tt class="docutils literal">fg</tt></dt>
<dd>Foreground color for the ordinary tile. Defaults to COLOR_GREY (7).</dd>
<dt><tt class="docutils literal">bg</tt></dt>
<dd>Background color for the ordinary tile. Defaults to COLOR_BLACK (0).</dd>
<dt><tt class="docutils literal">bold</tt></dt>
<dd>Bright/bold text flag. If <em>nil</em>, computed based on (fg &amp; 8); fg is masked to 3 bits.
Otherwise should be <em>true/false</em>.</dd>
<dt><tt class="docutils literal">tile</tt></dt>
<dd>Graphical tile id. Ignored unless [GRAPHICS:YES] was in init.txt.</dd>
<dt><tt class="docutils literal">tile_color = true</tt></dt>
<dd>Specifies that the tile should be shaded with <em>fg/bg</em>.</dd>
<dt><tt class="docutils literal">tile_fg, tile_bg</tt></dt>
<dd>If specified, overrides <em>tile_color</em> and supplies shading colors directly.</dd>
</dl>
</blockquote>
<p>Alternatively, it may be a pre-parsed native object with the following API:</p>
<ul>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.pen.make(base[,pen_or_fg,bg,bold])</span></tt></p>
<p>Creates a new pre-parsed pen by combining its arguments according to the
following rules:</p>
<ol class="arabic simple">
<li>The <tt class="docutils literal">base</tt> argument may be a pen object, a pen table as specified above,
or a single color value. In the single value case, it is split into
<tt class="docutils literal">fg</tt> and <tt class="docutils literal">bold</tt> properties, and others are initialized to 0.
This argument will be converted to a pre-parsed object and returned
if there are no other arguments.</li>
<li>If the <tt class="docutils literal">pen_or_fg</tt> argument is specified as a table or object, it
completely replaces the base, and is returned instead of it.</li>
<li>Otherwise, the non-nil subset of the optional arguments is used
to update the <tt class="docutils literal">fg</tt>, <tt class="docutils literal">bg</tt> and <tt class="docutils literal">bold</tt> properties of the base.
If the <tt class="docutils literal">bold</tt> flag is <em>nil</em>, but <em>pen_or_fg</em> is a number, <tt class="docutils literal">bold</tt>
is deduced from it like in the simple base case.</li>
</ol>
<p>This function always returns a new pre-parsed pen, or <em>nil</em>.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.pen.parse(base[,pen_or_fg,bg,bold])</span></tt></p>
<p>Exactly like the above function, but returns <tt class="docutils literal">base</tt> or <tt class="docutils literal">pen_or_fg</tt>
directly if they are already a pre-parsed native object.</p>
</li>
<li><p class="first"><tt class="docutils literal">pen.property</tt>, <tt class="docutils literal">pen.property = value</tt>, <tt class="docutils literal">pairs(pen)</tt></p>
<p>Pre-parsed pens support reading and setting their properties,
but don't behave exactly like a simple table would; for instance,
assigning to <tt class="docutils literal">pen.tile_color</tt> also resets <tt class="docutils literal">pen.tile_fg</tt> and
<tt class="docutils literal">pen.tile_bg</tt> to <em>nil</em>.</p>
</li>
</ul>
<p>In order to actually be able to paint to the screen, it is necessary
to create and register a viewscreen (basically a modal dialog) with
the game.</p>

@ -1403,31 +1403,14 @@ Basic painting functions:
* ``dfhack.screen.paintTile(pen,x,y[,char,tile])``
Paints a tile using given parameters. Pen is a table with following possible fields:
``ch``
Provides the ordinary tile character, as either a 1-character string or a number.
Can be overridden with the ``char`` function parameter.
``fg``
Foreground color for the ordinary tile. Defaults to COLOR_GREY (7).
``bg``
Background color for the ordinary tile. Defaults to COLOR_BLACK (0).
``bold``
Bright/bold text flag. If *nil*, computed based on (fg & 8); fg is masked to 3 bits.
Otherwise should be *true/false*.
``tile``
Graphical tile id. Ignored unless [GRAPHICS:YES] was in init.txt.
``tile_color = true``
Specifies that the tile should be shaded with *fg/bg*.
``tile_fg, tile_bg``
If specified, overrides *tile_color* and supplies shading colors directly.
Paints a tile using given parameters. See below for a description of pen.
Returns *false* if coordinates out of bounds, or other error.
* ``dfhack.screen.readTile(x,y)``
Retrieves the contents of the specified tile from the screen buffers.
Returns a pen, or *nil* if invalid or TrueType.
Returns a pen object, or *nil* if invalid or TrueType.
* ``dfhack.screen.paintString(pen,x,y,text)``
@ -1458,6 +1441,61 @@ Basic painting functions:
Requests repaint of the screen by setting a flag. Unlike other
functions in this section, this may be used at any time.
The "pen" argument used by functions above may be represented by
a table with the following possible fields:
``ch``
Provides the ordinary tile character, as either a 1-character string or a number.
Can be overridden with the ``char`` function parameter.
``fg``
Foreground color for the ordinary tile. Defaults to COLOR_GREY (7).
``bg``
Background color for the ordinary tile. Defaults to COLOR_BLACK (0).
``bold``
Bright/bold text flag. If *nil*, computed based on (fg & 8); fg is masked to 3 bits.
Otherwise should be *true/false*.
``tile``
Graphical tile id. Ignored unless [GRAPHICS:YES] was in init.txt.
``tile_color = true``
Specifies that the tile should be shaded with *fg/bg*.
``tile_fg, tile_bg``
If specified, overrides *tile_color* and supplies shading colors directly.
Alternatively, it may be a pre-parsed native object with the following API:
* ``dfhack.pen.make(base[,pen_or_fg,bg,bold])``
Creates a new pre-parsed pen by combining its arguments according to the
following rules:
1. The ``base`` argument may be a pen object, a pen table as specified above,
or a single color value. In the single value case, it is split into
``fg`` and ``bold`` properties, and others are initialized to 0.
This argument will be converted to a pre-parsed object and returned
if there are no other arguments.
2. If the ``pen_or_fg`` argument is specified as a table or object, it
completely replaces the base, and is returned instead of it.
3. Otherwise, the non-nil subset of the optional arguments is used
to update the ``fg``, ``bg`` and ``bold`` properties of the base.
If the ``bold`` flag is *nil*, but *pen_or_fg* is a number, ``bold``
is deduced from it like in the simple base case.
This function always returns a new pre-parsed pen, or *nil*.
* ``dfhack.pen.parse(base[,pen_or_fg,bg,bold])``
Exactly like the above function, but returns ``base`` or ``pen_or_fg``
directly if they are already a pre-parsed native object.
* ``pen.property``, ``pen.property = value``, ``pairs(pen)``
Pre-parsed pens support reading and setting their properties,
but don't behave exactly like a simple table would; for instance,
assigning to ``pen.tile_color`` also resets ``pen.tile_fg`` and
``pen.tile_bg`` to *nil*.
In order to actually be able to paint to the screen, it is necessary
to create and register a viewscreen (basically a modal dialog) with
the game.

@ -725,6 +725,316 @@ static void OpenMatinfo(lua_State *state)
lua_pop(state, 1);
}
/**************
* Pen object *
**************/
static int DFHACK_PEN_TOKEN = 0;
void Lua::Push(lua_State *L, const Screen::Pen &info)
{
if (!info.valid())
{
lua_pushnil(L);
return;
}
void *pdata = lua_newuserdata(L, sizeof(Pen));
lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_PEN_TOKEN);
lua_setmetatable(L, -2);
new (pdata) Pen(info);
}
static Pen *check_pen_native(lua_State *L, int index)
{
lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_PEN_TOKEN);
if (!lua_getmetatable(L, index) || !lua_rawequal(L, -1, -2))
luaL_argerror(L, index, "not a pen object");
lua_pop(L, 2);
return (Pen*)lua_touserdata(L, index);
}
void Lua::CheckPen(lua_State *L, Screen::Pen *pen, int index, bool allow_nil, bool allow_color)
{
index = lua_absindex(L, index);
luaL_checkany(L, index);
if (lua_isnil(L, index))
{
if (!allow_nil)
luaL_argerror(L, index, "nil pen not allowed");
*pen = Pen(0,0,0,-1);
}
else if (lua_isuserdata(L, index))
{
*pen = *check_pen_native(L, index);
}
else if (allow_color && lua_isnumber(L, index))
{
*pen = Pen(0, lua_tointeger(L, index)&15, 0);
}
else
{
luaL_checktype(L, index, LUA_TTABLE);
decode_pen(L, *pen, index);
}
}
static int adjust_pen(lua_State *L, bool no_copy)
{
lua_settop(L, 4);
Pen pen;
int iidx = 1;
Lua::CheckPen(L, &pen, 1, true, true);
if (!lua_isnil(L, 2) || !lua_isnil(L, 3) || !lua_isnil(L, 4))
{
if (lua_isnumber(L, 2) || lua_isnil(L, 2))
{
if (!pen.valid())
pen = Pen();
iidx = -1;
pen.fg = luaL_optint(L, 2, pen.fg) & 15;
pen.bg = luaL_optint(L, 3, pen.bg);
if (!lua_isnil(L, 4))
pen.bold = lua_toboolean(L, 4);
else if (!lua_isnil(L, 2))
{
pen.bold = !!(pen.fg & 8);
pen.fg &= 7;
}
}
else
{
iidx = 2;
Lua::CheckPen(L, &pen, 2, false, false);
}
}
if (no_copy && iidx > 0 && lua_isuserdata(L, iidx))
lua_pushvalue(L, iidx);
else
Lua::Push(L, pen);
return 1;
}
static int dfhack_pen_parse(lua_State *L)
{
return adjust_pen(L, true);
}
static int dfhack_pen_make(lua_State *L)
{
return adjust_pen(L, false);
}
static void make_pen_table(lua_State *L, Pen &pen)
{
if (!pen.valid())
luaL_error(L, "invalid pen state");
else
{
lua_newtable(L);
lua_pushinteger(L, (unsigned char)pen.ch); lua_setfield(L, -2, "ch");
lua_pushinteger(L, pen.fg); lua_setfield(L, -2, "fg");
lua_pushinteger(L, pen.bg); lua_setfield(L, -2, "bg");
lua_pushboolean(L, pen.bold); lua_setfield(L, -2, "bold");
if (pen.tile)
{
lua_pushinteger(L, pen.tile); lua_setfield(L, -2, "tile");
}
switch (pen.tile_mode) {
case Pen::CharColor:
lua_pushboolean(L, true); lua_setfield(L, -2, "tile_color");
break;
case Pen::TileColor:
lua_pushinteger(L, pen.tile_fg); lua_setfield(L, -2, "tile_fg");
lua_pushinteger(L, pen.tile_bg); lua_setfield(L, -2, "tile_bg");
break;
default:
lua_pushboolean(L, false); lua_setfield(L, -2, "tile_color");
break;
}
}
}
static void get_pen_mirror(lua_State *L, int idx)
{
lua_getuservalue(L, idx);
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
Pen pen;
Lua::CheckPen(L, &pen, idx, false, false);
make_pen_table(L, pen);
lua_dup(L);
lua_setuservalue(L, idx);
}
}
static int dfhack_pen_index(lua_State *L)
{
lua_settop(L, 2);
luaL_checktype(L, 1, LUA_TUSERDATA);
// check metatable
if (!lua_getmetatable(L, 1))
luaL_argerror(L, 1, "must be a pen");
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1))
return 1;
// otherwise read from the mirror table, creating it if necessary
lua_settop(L, 2);
get_pen_mirror(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
return 1;
}
static int pen_pnext(lua_State *L)
{
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
if (lua_next(L, lua_upvalueindex(1)))
return 2;
lua_pushnil(L);
return 1;
}
static int dfhack_pen_pairs(lua_State *L)
{
luaL_checktype(L, 1, LUA_TUSERDATA);
get_pen_mirror(L, 1);
lua_pushcclosure(L, pen_pnext, 1);
lua_pushnil(L);
lua_pushnil(L);
return 3;
}
const char *const pen_fields[] = {
"ch", "fg", "bold", "bg", "tile", "tile_color", "tile_fg", "tile_bg", NULL
};
static int dfhack_pen_newindex(lua_State *L)
{
lua_settop(L, 3);
luaL_checktype(L, 1, LUA_TUSERDATA);
int id = luaL_checkoption(L, 2, NULL, pen_fields);
int arg = 0;
Pen &pen = *check_pen_native(L, 1);
bool wipe_tile = false, wipe_tc = false;
switch (id) {
case 0:
if (lua_type(L, 3) != LUA_TNUMBER)
arg = (unsigned char)*luaL_checkstring(L, 3);
else
arg = luaL_checkint(L, 3);
pen.ch = arg;
lua_pushinteger(L, (unsigned char)pen.ch);
break;
case 1:
pen.fg = luaL_checkint(L, 3) & 15;
lua_pushinteger(L, pen.fg);
break;
case 2:
pen.bold = lua_toboolean(L, 3);
lua_pushboolean(L, pen.bold);
break;
case 3:
pen.bg = luaL_checkint(L, 3) & 15;
lua_pushinteger(L, pen.bg);
break;
case 4:
arg = lua_isnil(L, 3) ? 0 : luaL_checkint(L, 3);
if (arg < 0)
luaL_argerror(L, 3, "invalid tile index");
pen.tile = arg;
if (pen.tile)
lua_pushinteger(L, pen.tile);
else
lua_pushnil(L);
break;
case 5:
wipe_tile = (pen.tile_mode == Pen::TileColor);
pen.tile_mode = lua_toboolean(L, 3) ? Pen::CharColor : Pen::AsIs;
lua_pushboolean(L, pen.tile_mode == Pen::CharColor);
break;
case 6:
if (pen.tile_mode != Pen::TileColor) { wipe_tc = true; pen.tile_bg = 0; }
pen.tile_fg = luaL_checkint(L, 3) & 15;
pen.tile_mode = Pen::TileColor;
lua_pushinteger(L, pen.tile_fg);
break;
case 7:
if (pen.tile_mode != Pen::TileColor) { wipe_tc = true; pen.tile_fg = 7; }
pen.tile_bg = luaL_checkint(L, 3) & 15;
pen.tile_mode = Pen::TileColor;
lua_pushinteger(L, pen.tile_bg);
break;
}
lua_getuservalue(L, 1);
if (!lua_isnil(L, -1))
{
lua_remove(L, 3);
lua_insert(L, 2);
lua_rawset(L, 2);
if (wipe_tc) {
lua_pushnil(L); lua_setfield(L, 2, "tile_color");
lua_pushinteger(L, pen.tile_fg); lua_setfield(L, 2, "tile_fg");
lua_pushinteger(L, pen.tile_bg); lua_setfield(L, 2, "tile_bg");
}
if (wipe_tile) {
lua_pushnil(L); lua_setfield(L, 2, "tile_fg");
lua_pushnil(L); lua_setfield(L, 2, "tile_bg");
}
}
return 0;
}
static const luaL_Reg dfhack_pen_funcs[] = {
{ "parse", dfhack_pen_parse },
{ "make", dfhack_pen_make },
{ "__index", dfhack_pen_index },
{ "__pairs", dfhack_pen_pairs },
{ "__newindex", dfhack_pen_newindex },
{ NULL, NULL }
};
static void OpenPen(lua_State *state)
{
luaL_getsubtable(state, lua_gettop(state), "pen");
lua_dup(state);
lua_rawsetp(state, LUA_REGISTRYINDEX, &DFHACK_PEN_TOKEN);
luaL_setfuncs(state, dfhack_pen_funcs, 0);
lua_pop(state, 1);
}
/************************
* Wrappers for C++ API *
************************/
@ -1251,7 +1561,7 @@ static int screen_getWindowSize(lua_State *L)
static int screen_paintTile(lua_State *L)
{
Pen pen;
decode_pen(L, pen, 1);
Lua::CheckPen(L, &pen, 1);
int x = luaL_checkint(L, 2);
int y = luaL_checkint(L, 3);
if (lua_gettop(L) >= 4 && !lua_isnil(L, 4))
@ -1272,44 +1582,14 @@ static int screen_readTile(lua_State *L)
int x = luaL_checkint(L, 1);
int y = luaL_checkint(L, 2);
Pen pen = Screen::readTile(x, y);
if (!pen.valid())
{
lua_pushnil(L);
}
else
{
lua_newtable(L);
lua_pushinteger(L, pen.ch); lua_setfield(L, -2, "ch");
lua_pushinteger(L, pen.fg); lua_setfield(L, -2, "fg");
lua_pushinteger(L, pen.bg); lua_setfield(L, -2, "bg");
lua_pushboolean(L, pen.bold); lua_setfield(L, -2, "bold");
if (pen.tile)
{
lua_pushinteger(L, pen.tile); lua_setfield(L, -2, "tile");
switch (pen.tile_mode) {
case Pen::CharColor:
lua_pushboolean(L, true); lua_setfield(L, -2, "tile_color");
break;
case Pen::TileColor:
lua_pushinteger(L, pen.tile_fg); lua_setfield(L, -2, "tile_fg");
lua_pushinteger(L, pen.tile_bg); lua_setfield(L, -2, "tile_bg");
break;
default:
break;
}
}
}
Lua::Push(L, pen);
return 1;
}
static int screen_paintString(lua_State *L)
{
Pen pen;
decode_pen(L, pen, 1);
Lua::CheckPen(L, &pen, 1);
int x = luaL_checkint(L, 2);
int y = luaL_checkint(L, 3);
const char *text = luaL_checkstring(L, 4);
@ -1320,7 +1600,7 @@ static int screen_paintString(lua_State *L)
static int screen_fillRect(lua_State *L)
{
Pen pen;
decode_pen(L, pen, 1);
Lua::CheckPen(L, &pen, 1);
int x1 = luaL_checkint(L, 2);
int y1 = luaL_checkint(L, 3);
int x2 = luaL_checkint(L, 4);
@ -1720,6 +2000,7 @@ void OpenDFHackApi(lua_State *state)
{
OpenPersistent(state);
OpenMatinfo(state);
OpenPen(state);
LuaWrapper::SetFunctionWrappers(state, dfhack_module);
OpenModule(state, "gui", dfhack_gui_module);

@ -41,6 +41,9 @@ namespace DFHack {
namespace Units {
struct NoblePosition;
}
namespace Screen {
struct Pen;
};
}
namespace DFHack {namespace Lua {
@ -285,6 +288,7 @@ namespace DFHack {namespace Lua {
DFHACK_EXPORT void Push(lua_State *state, df::coord2d obj);
void Push(lua_State *state, const Units::NoblePosition &pos);
DFHACK_EXPORT void Push(lua_State *state, MaterialInfo &info);
DFHACK_EXPORT void Push(lua_State *state, const Screen::Pen &info);
template<class T> inline void Push(lua_State *state, T *ptr) {
PushDFObject(state, ptr);
}
@ -315,6 +319,8 @@ namespace DFHack {namespace Lua {
DFHACK_EXPORT int PushPosXYZ(lua_State *state, df::coord pos);
DFHACK_EXPORT int PushPosXY(lua_State *state, df::coord2d pos);
DFHACK_EXPORT void CheckPen(lua_State *L, Screen::Pen *pen, int index, bool allow_nil = false, bool allow_color = true);
DFHACK_EXPORT bool IsCoreContext(lua_State *state);
namespace Event {

@ -76,6 +76,8 @@ namespace DFHack
bool valid() const { return tile >= 0; }
bool empty() const { return ch == 0 && tile == 0; }
// NOTE: LuaApi.cpp assumes this struct is plain data and has empty destructor
Pen(char ch = 0, int8_t fg = 7, int8_t bg = 0, int tile = 0, bool color_tile = false)
: ch(ch), fg(fg&7), bg(bg), bold(!!(fg&8)),
tile(tile), tile_mode(color_tile ? CharColor : AsIs), tile_fg(0), tile_bg(0)

@ -6,7 +6,9 @@ local dscreen = dfhack.screen
USE_GRAPHICS = dscreen.inGraphicsMode()
CLEAR_PEN = {ch=32,fg=0,bg=0}
local to_pen = dfhack.pen.parse
CLEAR_PEN = to_pen{ch=32,fg=0,bg=0}
function simulateInput(screen,...)
local keys = {}
@ -116,16 +118,6 @@ function blink_visible(delay)
return math.floor(dfhack.getTickCount()/delay) % 2 == 0
end
function to_pen(default, pen, bg, bold)
if pen == nil then
return default or {}
elseif type(pen) ~= 'table' then
return {fg=pen,bg=bg,bold=bold}
else
return pen
end
end
function getKeyDisplay(code)
if type(code) == 'string' then
code = df.interface_key[code]
@ -215,7 +207,8 @@ Painter = defclass(Painter, ViewRect)
function Painter:init(args)
self.x = self.x1
self.y = self.y1
self.cur_pen = to_pen(nil, args.pen or COLOR_GREY)
self.cur_pen = to_pen(args.pen or COLOR_GREY)
self.cur_key_pen = to_pen(args.key_pen or COLOR_LIGHTGREEN)
end
function Painter.new(rect, pen)
@ -241,6 +234,7 @@ end
function Painter:viewport(x,y,w,h)
local vp = ViewRect.viewport(x,y,w,h)
vp.cur_pen = self.cur_pen
vp.cur_key_pen = self.cur_key_pen
return mkinstance(Painter, vp):seek(0,0)
end
@ -280,10 +274,12 @@ function Painter:pen(pen,...)
end
function Painter:color(fg,bold,bg)
self.cur_pen = copyall(self.cur_pen)
self.cur_pen.fg = fg
self.cur_pen.bold = bold
if bg then self.cur_pen.bg = bg end
self.cur_pen = to_pen(self.cur_pen, fg, bg, bold)
return self
end
function Painter:key_pen(pen,...)
self.cur_key_pen = to_pen(self.cur_key_pen, pen, ...)
return self
end
@ -339,10 +335,10 @@ function Painter:string(text,pen,...)
return self:advance(#text, nil)
end
function Painter:key(code,pen,bg,...)
function Painter:key(code,pen,...)
return self:string(
getKeyDisplay(code),
pen or COLOR_LIGHTGREEN, bg or self.cur_pen.bg, ...
to_pen(self.cur_key_pen, pen, ...)
)
end
@ -557,28 +553,28 @@ end
-- Plain grey-colored frame.
GREY_FRAME = {
frame_pen = { ch = ' ', fg = COLOR_BLACK, bg = COLOR_GREY },
title_pen = { fg = COLOR_BLACK, bg = COLOR_WHITE },
signature_pen = { fg = COLOR_BLACK, bg = COLOR_GREY },
frame_pen = to_pen{ ch = ' ', fg = COLOR_BLACK, bg = COLOR_GREY },
title_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_WHITE },
signature_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_GREY },
}
-- The usual boundary used by the DF screens. Often has fancy pattern in tilesets.
BOUNDARY_FRAME = {
frame_pen = { ch = 0xDB, fg = COLOR_DARKGREY, bg = COLOR_BLACK },
title_pen = { fg = COLOR_BLACK, bg = COLOR_GREY },
signature_pen = { fg = COLOR_BLACK, bg = COLOR_DARKGREY },
frame_pen = to_pen{ ch = 0xDB, fg = COLOR_DARKGREY, bg = COLOR_BLACK },
title_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_GREY },
signature_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_DARKGREY },
}
GREY_LINE_FRAME = {
frame_pen = { ch = 206, fg = COLOR_GREY, bg = COLOR_BLACK },
h_frame_pen = { ch = 205, fg = COLOR_GREY, bg = COLOR_BLACK },
v_frame_pen = { ch = 186, fg = COLOR_GREY, bg = COLOR_BLACK },
lt_frame_pen = { ch = 201, fg = COLOR_GREY, bg = COLOR_BLACK },
lb_frame_pen = { ch = 200, fg = COLOR_GREY, bg = COLOR_BLACK },
rt_frame_pen = { ch = 187, fg = COLOR_GREY, bg = COLOR_BLACK },
rb_frame_pen = { ch = 188, fg = COLOR_GREY, bg = COLOR_BLACK },
title_pen = { fg = COLOR_BLACK, bg = COLOR_GREY },
signature_pen = { fg = COLOR_DARKGREY, bg = COLOR_BLACK },
frame_pen = to_pen{ ch = 206, fg = COLOR_GREY, bg = COLOR_BLACK },
h_frame_pen = to_pen{ ch = 205, fg = COLOR_GREY, bg = COLOR_BLACK },
v_frame_pen = to_pen{ ch = 186, fg = COLOR_GREY, bg = COLOR_BLACK },
lt_frame_pen = to_pen{ ch = 201, fg = COLOR_GREY, bg = COLOR_BLACK },
lb_frame_pen = to_pen{ ch = 200, fg = COLOR_GREY, bg = COLOR_BLACK },
rt_frame_pen = to_pen{ ch = 187, fg = COLOR_GREY, bg = COLOR_BLACK },
rb_frame_pen = to_pen{ ch = 188, fg = COLOR_GREY, bg = COLOR_BLACK },
title_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_GREY },
signature_pen = to_pen{ fg = COLOR_DARKGREY, bg = COLOR_BLACK },
}
function paint_frame(x1,y1,x2,y2,style,title)

@ -160,8 +160,8 @@ function ListBox:preinit(info)
end
function ListBox:init(info)
local spen = gui.to_pen(COLOR_CYAN, self.select_pen, nil, false)
local cpen = gui.to_pen(COLOR_LIGHTCYAN, self.cursor_pen or self.select_pen, nil, true)
local spen = dfhack.pen.parse(COLOR_CYAN, self.select_pen, nil, false)
local cpen = dfhack.pen.parse(COLOR_LIGHTCYAN, self.cursor_pen or self.select_pen, nil, true)
local list_widget = widgets.List
if self.with_filter then