Fork of Tangara with customizations
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
tangara-fw/lib/luavgl/src/style.c

702 lines
23 KiB

#include "luavgl.h"
#include "private.h"
typedef struct {
lv_style_t style;
} luavgl_style_t;
typedef enum {
STYLE_TYPE_INT = 1,
STYLE_TYPE_COLOR,
STYLE_TYPE_POINTER, /* a pointer from light-userdata */
STYLE_TYPE_IMGSRC, /* string or light-userdata, similar to pointer */
STYLE_TYPE_TABLE, /* value is in table */
/* Flag of none-simple type. All extended styles are special case. */
STYLE_TYPE_SPECIAL = 0x10,
} style_type_t;
enum {
LV_STYLE_SIZE = _LV_STYLE_LAST_BUILT_IN_PROP + 1,
LV_STYLE_PAD_ALL,
LV_STYLE_PAD_VER,
LV_STYLE_PAD_HOR,
LV_STYLE_PAD_GAP,
_LV_STYLE_FLEX,
_LV_STYLE_FLEX_FLOW, /* style not const, need to call related API */
_LV_STYLE_FLEX_MAIN_PLACE,
_LV_STYLE_FLEX_CROSS_PLACE,
_LV_STYLE_FLEX_TRACK_PLACE,
_LV_STYLE_FLEX_GROW,
};
/* callback made when style matched. */
typedef void (*style_set_cb_t)(lv_style_prop_t prop, lv_style_value_t value,
void *args);
static const struct style_map_s {
const char *name;
lv_style_prop_t prop;
style_type_t type;
} g_style_map[] = {
{"width", LV_STYLE_WIDTH, STYLE_TYPE_INT },
{"min_width", LV_STYLE_MIN_WIDTH, STYLE_TYPE_INT },
{"max_width", LV_STYLE_MAX_WIDTH, STYLE_TYPE_INT },
{"height", LV_STYLE_HEIGHT, STYLE_TYPE_INT },
{"min_height", LV_STYLE_MIN_HEIGHT, STYLE_TYPE_INT },
{"max_height", LV_STYLE_MAX_HEIGHT, STYLE_TYPE_INT },
{"x", LV_STYLE_X, STYLE_TYPE_INT },
{"y", LV_STYLE_Y, STYLE_TYPE_INT },
{"align", LV_STYLE_ALIGN, STYLE_TYPE_INT },
{"transform_width", LV_STYLE_TRANSFORM_WIDTH, STYLE_TYPE_INT },
{"transform_height", LV_STYLE_TRANSFORM_HEIGHT, STYLE_TYPE_INT },
{"translate_x", LV_STYLE_TRANSLATE_X, STYLE_TYPE_INT },
{"translate_y", LV_STYLE_TRANSLATE_Y, STYLE_TYPE_INT },
{"transform_zoom", LV_STYLE_TRANSFORM_ZOOM, STYLE_TYPE_INT },
{"transform_angle", LV_STYLE_TRANSFORM_ANGLE, STYLE_TYPE_INT },
{"transform_pivot_x", LV_STYLE_TRANSFORM_PIVOT_X, STYLE_TYPE_INT },
{"transform_pivot_y", LV_STYLE_TRANSFORM_PIVOT_Y, STYLE_TYPE_INT },
{"pad_top", LV_STYLE_PAD_TOP, STYLE_TYPE_INT },
{"pad_bottom", LV_STYLE_PAD_BOTTOM, STYLE_TYPE_INT },
{"pad_left", LV_STYLE_PAD_LEFT, STYLE_TYPE_INT },
{"pad_right", LV_STYLE_PAD_RIGHT, STYLE_TYPE_INT },
{"pad_row", LV_STYLE_PAD_ROW, STYLE_TYPE_INT },
{"pad_column", LV_STYLE_PAD_COLUMN, STYLE_TYPE_INT },
{"pad_gap", LV_STYLE_PAD_GAP, STYLE_TYPE_INT },
{"bg_color", LV_STYLE_BG_COLOR, STYLE_TYPE_COLOR },
{"bg_opa", LV_STYLE_BG_OPA, STYLE_TYPE_INT },
{"bg_grad_color", LV_STYLE_BG_GRAD_COLOR, STYLE_TYPE_COLOR },
{"bg_grad_dir", LV_STYLE_BG_GRAD_DIR, STYLE_TYPE_INT },
{"bg_main_stop", LV_STYLE_BG_MAIN_STOP, STYLE_TYPE_INT },
{"bg_grad_stop", LV_STYLE_BG_GRAD_STOP, STYLE_TYPE_INT },
{"bg_dither_mode", LV_STYLE_BG_DITHER_MODE, STYLE_TYPE_INT },
{"bg_img_src", LV_STYLE_BG_IMG_SRC, STYLE_TYPE_IMGSRC },
{"bg_img_opa", LV_STYLE_BG_IMG_OPA, STYLE_TYPE_INT },
{"bg_img_recolor", LV_STYLE_BG_IMG_RECOLOR, STYLE_TYPE_COLOR },
{"bg_img_recolor_opa", LV_STYLE_BG_IMG_RECOLOR_OPA, STYLE_TYPE_INT },
{"bg_img_tiled", LV_STYLE_BG_IMG_TILED, STYLE_TYPE_INT },
{"border_color", LV_STYLE_BORDER_COLOR, STYLE_TYPE_COLOR },
{"border_opa", LV_STYLE_BORDER_OPA, STYLE_TYPE_INT },
{"border_width", LV_STYLE_BORDER_WIDTH, STYLE_TYPE_INT },
{"border_side", LV_STYLE_BORDER_SIDE, STYLE_TYPE_INT },
{"border_post", LV_STYLE_BORDER_POST, STYLE_TYPE_INT },
{"outline_width", LV_STYLE_OUTLINE_WIDTH, STYLE_TYPE_INT },
{"outline_color", LV_STYLE_OUTLINE_COLOR, STYLE_TYPE_COLOR },
{"outline_opa", LV_STYLE_OUTLINE_OPA, STYLE_TYPE_INT },
{"outline_pad", LV_STYLE_OUTLINE_PAD, STYLE_TYPE_INT },
{"shadow_width", LV_STYLE_SHADOW_WIDTH, STYLE_TYPE_INT },
{"shadow_ofs_x", LV_STYLE_SHADOW_OFS_X, STYLE_TYPE_INT },
{"shadow_ofs_y", LV_STYLE_SHADOW_OFS_Y, STYLE_TYPE_INT },
{"shadow_spread", LV_STYLE_SHADOW_SPREAD, STYLE_TYPE_INT },
{"shadow_color", LV_STYLE_SHADOW_COLOR, STYLE_TYPE_COLOR },
{"shadow_opa", LV_STYLE_SHADOW_OPA, STYLE_TYPE_INT },
{"img_opa", LV_STYLE_IMG_OPA, STYLE_TYPE_INT },
{"img_recolor", LV_STYLE_IMG_RECOLOR, STYLE_TYPE_COLOR },
{"img_recolor_opa", LV_STYLE_IMG_RECOLOR_OPA, STYLE_TYPE_INT },
{"line_width", LV_STYLE_LINE_WIDTH, STYLE_TYPE_INT },
{"line_dash_width", LV_STYLE_LINE_DASH_WIDTH, STYLE_TYPE_INT },
{"line_dash_gap", LV_STYLE_LINE_DASH_GAP, STYLE_TYPE_INT },
{"line_rounded", LV_STYLE_LINE_ROUNDED, STYLE_TYPE_INT },
{"line_color", LV_STYLE_LINE_COLOR, STYLE_TYPE_INT },
{"line_opa", LV_STYLE_LINE_OPA, STYLE_TYPE_INT },
{"arc_width", LV_STYLE_ARC_WIDTH, STYLE_TYPE_INT },
{"arc_img_src", LV_STYLE_ARC_IMG_SRC, STYLE_TYPE_IMGSRC },
{"arc_rounded", LV_STYLE_ARC_ROUNDED, STYLE_TYPE_INT },
{"arc_color", LV_STYLE_ARC_COLOR, STYLE_TYPE_COLOR },
{"arc_opa", LV_STYLE_ARC_OPA, STYLE_TYPE_INT },
{"text_color", LV_STYLE_TEXT_COLOR, STYLE_TYPE_COLOR },
{"text_opa", LV_STYLE_TEXT_OPA, STYLE_TYPE_INT },
{"text_font", LV_STYLE_TEXT_FONT, STYLE_TYPE_POINTER }, /* light-userdata */
{"text_letter_space", LV_STYLE_TEXT_LETTER_SPACE, STYLE_TYPE_INT },
{"text_line_space", LV_STYLE_TEXT_LINE_SPACE, STYLE_TYPE_INT },
{"text_decor", LV_STYLE_TEXT_DECOR, STYLE_TYPE_INT },
{"text_align", LV_STYLE_TEXT_ALIGN, STYLE_TYPE_INT },
{"radius", LV_STYLE_RADIUS, STYLE_TYPE_INT },
{"clip_corner", LV_STYLE_CLIP_CORNER, STYLE_TYPE_INT },
{"opa", LV_STYLE_OPA, STYLE_TYPE_INT },
{"color_filter_opa", LV_STYLE_COLOR_FILTER_OPA, STYLE_TYPE_INT },
{"anim_time", LV_STYLE_ANIM_TIME, STYLE_TYPE_INT },
{"anim_speed", LV_STYLE_ANIM_SPEED, STYLE_TYPE_INT },
{"blend_mode", LV_STYLE_BLEND_MODE, STYLE_TYPE_INT },
{"layout", LV_STYLE_LAYOUT, STYLE_TYPE_INT },
{"base_dir", LV_STYLE_BASE_DIR, STYLE_TYPE_INT },
/* need to build pointer from table parameter */
{"bg_grad", LV_STYLE_BG_GRAD, STYLE_TYPE_SPECIAL }, /* pointer from table */
{"color_filter_dsc", LV_STYLE_COLOR_FILTER_DSC, STYLE_TYPE_SPECIAL }, /**/
{"anim", LV_STYLE_ANIM, STYLE_TYPE_SPECIAL }, /* anim para */
{"transition", LV_STYLE_TRANSITION, STYLE_TYPE_SPECIAL }, /* transition */
/* styles combined */
{"size", LV_STYLE_SIZE, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"pad_all", LV_STYLE_PAD_ALL, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"pad_ver", LV_STYLE_PAD_VER, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"pad_hor", LV_STYLE_PAD_HOR, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
/* styles for layout */
{"flex", _LV_STYLE_FLEX, STYLE_TYPE_SPECIAL | STYLE_TYPE_TABLE},
{"flex_flow", _LV_STYLE_FLEX_FLOW, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"flex_main_place", _LV_STYLE_FLEX_MAIN_PLACE,
STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"flex_cross_place", _LV_STYLE_FLEX_CROSS_PLACE,
STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"flex_track_place", _LV_STYLE_FLEX_TRACK_PLACE,
STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"flex_grow", _LV_STYLE_FLEX_GROW, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
};
#define STYLE_MAP_LEN (sizeof(g_style_map) / sizeof(g_style_map[0]))
/**
* lv_style
*/
static luavgl_style_t *luavgl_check_style(lua_State *L, int index)
{
luavgl_style_t *v = *(luavgl_style_t **)luaL_checkudata(L, index, "lv_style");
return v;
}
static void lv_style_set_cb(lv_style_prop_t prop, lv_style_value_t value,
void *args)
{
lv_style_t *s = args;
lv_style_set_prop(s, prop, value);
}
static void lv_style_set_inherit_cb(lv_style_prop_t prop,
lv_style_value_t value, void *args)
{
lv_style_t *s = args;
lv_style_set_prop_meta(s, prop, LV_STYLE_PROP_META_INHERIT);
}
static uint8_t to_int(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return -1;
}
static lv_flex_align_t luavgl_to_flex_align(lua_State *L, int idx)
{
if (lua_type(L, idx) != LUA_TSTRING)
return LV_FLEX_ALIGN_START;
const char *str = lua_tostring(L, idx);
if (strcmp("flex-start", str) == 0)
return LV_FLEX_ALIGN_START;
if (strcmp("flex-end", str) == 0)
return LV_FLEX_ALIGN_END;
if (strcmp("center", str) == 0)
return LV_FLEX_ALIGN_CENTER;
if (strcmp("space-evenly", str) == 0)
return LV_FLEX_ALIGN_SPACE_EVENLY;
if (strcmp("space-around", str) == 0)
return LV_FLEX_ALIGN_SPACE_AROUND;
if (strcmp("space-between", str) == 0)
return LV_FLEX_ALIGN_SPACE_BETWEEN;
return LV_FLEX_ALIGN_START;
}
static int luavgl_set_flex_layout_kv(lua_State *L, style_set_cb_t cb,
void *args)
{
if (!lua_istable(L, -1)) {
debug("para should be table.");
return luaL_argerror(L, -1, "should be table.");
}
const char *str;
lv_flex_flow_t flow = LV_FLEX_FLOW_ROW;
lv_flex_align_t align;
/**
* flex-direction:
* row | row-reverse | column | column-reverse
*/
lua_getfield(L, -1, "flex_direction");
if (lua_type(L, -1) == LUA_TSTRING) {
str = lua_tostring(L, -1);
/* starts with */
if (strncmp("row", str, 3) == 0) {
flow = LV_FLEX_FLOW_ROW;
} else if (strncmp("column", str, 3) == 0) {
flow = LV_FLEX_FLOW_COLUMN;
}
/* if reverse presents */
if (strstr(str, "-reverse")) {
flow |= _LV_FLEX_REVERSE;
}
}
lua_pop(L, 1);
/**
* flex-wrap:
* nowrap | wrap | wrap-reverse;
*/
lua_getfield(L, -1, "flex_wrap");
if (lua_type(L, -1) == LUA_TSTRING) {
str = lua_tostring(L, -1);
if (strcmp("wrap", str) == 0) {
flow |= _LV_FLEX_WRAP;
} else if (strcmp("wrap-reverse", str) == 0) {
flow |= _LV_FLEX_WRAP | _LV_FLEX_REVERSE;
}
/* else: normal */
}
lua_pop(L, 1);
lv_style_value_t value = {0};
value.num = LV_LAYOUT_FLEX;
cb(LV_STYLE_LAYOUT, value, args);
value.num = flow;
cb(LV_STYLE_FLEX_FLOW, value, args);
/**
* justify-content
* flex-start | flex-end | center |
* space-between | space-around | space-evenly
*/
lua_getfield(L, -1, "justify_content");
if (lua_type(L, -1) == LUA_TSTRING) {
align = luavgl_to_flex_align(L, -1);
value.num = align;
cb(LV_STYLE_FLEX_MAIN_PLACE, value, args);
}
lua_pop(L, 1);
/**
* align-items
* flex-start | flex-end | center |
* space-between | space-around | space-evenly
*/
lua_getfield(L, -1, "align_items");
if (lua_type(L, -1) == LUA_TSTRING) {
align = luavgl_to_flex_align(L, -1);
value.num = align;
cb(LV_STYLE_FLEX_CROSS_PLACE, value, args);
}
lua_pop(L, 1);
/**
* align-content
* flex-start | flex-end | center |
* space-between | space-around | space-evenly
*/
lua_getfield(L, -1, "align_content");
if (lua_type(L, -1) == LUA_TSTRING) {
align = luavgl_to_flex_align(L, -1);
value.num = align;
cb(LV_STYLE_FLEX_TRACK_PLACE, value, args);
}
lua_pop(L, 1);
return 0;
}
/* is the style value on stack top is inherit special value */
static inline bool luavgl_is_style_inherit(lua_State *L)
{
const char *str;
return (lua_type(L, -1) == LUA_TSTRING) && (str = lua_tostring(L, -1)) &&
(strcmp(str, "inherit") == 0);
}
/**
* internal used API, called from style:set()
* key: stack[-2]
* value: stack[-1]
*
* @return 0 if succeed, -1 if failed.
*/
static int luavgl_set_style_kv(lua_State *L, style_set_cb_t cb, void *args)
{
const char *key = lua_tostring(L, -2);
if (key == NULL) {
debug("Null key, ignored.\n");
return -1;
}
/* map name to style value. */
lv_style_value_t value = {0};
const struct style_map_s *p = NULL;
for (int i = 0; i < STYLE_MAP_LEN; i++) {
if (strcmp(key, g_style_map[i].name) == 0) {
p = &g_style_map[i];
break;
}
}
if (p == NULL) /* not found */
return -1;
style_type_t type = p->type & 0x0f;
int v;
if (!luavgl_is_style_inherit(L)) {
/* get normal values */
switch (type) {
case STYLE_TYPE_INT:
v = luavgl_tointeger(L, -1);
value.num = v;
break;
case STYLE_TYPE_COLOR:
value.color = luavgl_tocolor(L, -1);
break;
case STYLE_TYPE_POINTER:
value.ptr = lua_touserdata(L, -1);
break;
case STYLE_TYPE_IMGSRC:
value.ptr = luavgl_toimgsrc(L, -1);
break;
case STYLE_TYPE_TABLE:
break;
default:
/* error, unkown type */
return luaL_error(L, "unknown style");
}
}
if (p->type & STYLE_TYPE_SPECIAL) {
switch ((int)p->prop) {
/* style combinations */
case LV_STYLE_SIZE:
cb(LV_STYLE_WIDTH, value, args);
cb(LV_STYLE_HEIGHT, value, args);
break;
case LV_STYLE_PAD_ALL:
cb(LV_STYLE_PAD_TOP, value, args);
cb(LV_STYLE_PAD_BOTTOM, value, args);
cb(LV_STYLE_PAD_LEFT, value, args);
cb(LV_STYLE_PAD_RIGHT, value, args);
break;
case LV_STYLE_PAD_VER:
cb(LV_STYLE_PAD_TOP, value, args);
cb(LV_STYLE_PAD_BOTTOM, value, args);
break;
case LV_STYLE_PAD_HOR:
cb(LV_STYLE_PAD_LEFT, value, args);
cb(LV_STYLE_PAD_RIGHT, value, args);
break;
case LV_STYLE_PAD_GAP:
cb(LV_STYLE_PAD_ROW, value, args);
cb(LV_STYLE_PAD_COLUMN, value, args);
break;
/* pointers needs to build from lua stack table */
case LV_STYLE_BG_GRAD:
break;
case LV_STYLE_COLOR_FILTER_DSC:
break;
case LV_STYLE_ANIM:
break;
case LV_STYLE_TRANSITION:
break;
/* layout styles that not constant */
case _LV_STYLE_FLEX_FLOW:
cb(LV_STYLE_FLEX_FLOW, value, args);
break;
case _LV_STYLE_FLEX_MAIN_PLACE:
cb(LV_STYLE_FLEX_MAIN_PLACE, value, args);
break;
case _LV_STYLE_FLEX_CROSS_PLACE:
cb(LV_STYLE_FLEX_CROSS_PLACE, value, args);
break;
case _LV_STYLE_FLEX_TRACK_PLACE:
cb(LV_STYLE_FLEX_TRACK_PLACE, value, args);
break;
case _LV_STYLE_FLEX_GROW:
cb(LV_STYLE_FLEX_GROW, value, args);
break;
case _LV_STYLE_FLEX: {
/* value is all on table */
luavgl_set_flex_layout_kv(L, cb, args);
break;
}
default:
break;
}
} else if (p->prop <= _LV_STYLE_LAST_BUILT_IN_PROP) {
cb(p->prop, value, args);
} else {
return luaL_error(L, "unknown style");
}
return 0;
}
/**
* style:set({x = 0, y = 0, bg_opa = 123})
*/
static int luavgl_style_set(lua_State *L)
{
luavgl_style_t *s = luavgl_check_style(L, 1);
if (!lua_istable(L, 2)) {
luaL_argerror(L, 2, "expect a table on 2nd para.");
return 0;
}
lua_pushnil(L); /* nil as initial key to iterate through table */
while (lua_next(L, -2)) {
/* -1: value, -2: key */
if (!lua_isstring(L, -2)) {
/* we expect string as key, ignore it if not */
debug("ignore non-string key in table.\n");
lua_pop(L, 1);
continue;
}
/* special value check */
bool inherit = luavgl_is_style_inherit(L);
luavgl_set_style_kv(L, inherit ? lv_style_set_inherit_cb : lv_style_set_cb,
s);
lua_pop(L, 1); /* remove value, keep the key to continue. */
}
return 0;
}
/**
* luavgl.Style({
* bg_color = 0xff0000,
* border_width = 1,
* })
*
* For simplicity, style need to be manually deleted `style:delete()` in order
* to be gc'ed.
*/
static int luavgl_style_create(lua_State *L)
{
luavgl_style_t *s = malloc(sizeof(luavgl_style_t));
if (s == NULL) {
return luaL_error(L, "No memory.");
}
lv_style_init(&s->style);
*(void **)lua_newuserdata(L, sizeof(void *)) = s;
luaL_getmetatable(L, "lv_style");
lua_setmetatable(L, -2);
lua_pushlightuserdata(L, s);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
lua_rotate(L, 1, 1); /* stack after: style-user-data, para */
luavgl_style_set(L);
lua_pop(L, 1); /* remove parameter table */
return 1;
}
/**
* style:remove_prop("width")
*/
static int luavgl_style_remove_prop(lua_State *L)
{
luavgl_style_t *s = luavgl_check_style(L, 1);
const char *name = lua_tostring(L, 2);
for (int i = 0; i < STYLE_MAP_LEN; i++) {
const struct style_map_s *p = &g_style_map[i];
if (strcmp(name, p->name) == 0) {
lv_style_remove_prop(&s->style, p->prop);
return 0;
}
}
return luaL_error(L, "unknown prop name: %s", name);
}
static int luavgl_style_delete(lua_State *L)
{
luavgl_style_t *s = luavgl_check_style(L, 1);
lua_pushlightuserdata(L, s);
lua_pushnil(L);
lua_rawset(L, LUA_REGISTRYINDEX);
return 1;
}
static int luavgl_style_gc(lua_State *L)
{
luavgl_style_t *s = luavgl_check_style(L, 1);
lv_style_reset(&s->style);
free(s);
debug("gc style:%p\n", s);
return 0;
}
/**
* lv_obj_style
*/
struct obj_style_s {
lv_obj_t *obj;
int selector;
};
static void obj_style_set_cb(lv_style_prop_t prop, lv_style_value_t value,
void *args)
{
struct obj_style_s *info = args;
lv_obj_set_local_style_prop(info->obj, prop, value, info->selector);
}
static void obj_style_inherit_set_cb(lv_style_prop_t prop,
lv_style_value_t value, void *args)
{
struct obj_style_s *info = args;
lv_obj_set_local_style_prop_meta(info->obj, prop, LV_STYLE_PROP_META_INHERIT,
info->selector);
}
static int luavgl_obj_set_style_kv(lua_State *L, lv_obj_t *obj, int selector)
{
struct obj_style_s info = {
.obj = obj,
.selector = selector,
};
/* special value check */
bool inherit = luavgl_is_style_inherit(L);
return luavgl_set_style_kv(
L, inherit ? obj_style_inherit_set_cb : obj_style_set_cb, &info);
}
/**
* obj:set_style({x = 0, y = 0, bg_opa = 123}, 0)
*/
static int luavgl_obj_set_style(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (obj == NULL) {
luaL_argerror(L, 1, "obj could already been deleted.");
return 0;
}
if (!lua_istable(L, 2)) {
luaL_argerror(L, 2, "expect a table on 2nd para.");
return 0;
}
int selector = 0;
if (!lua_isnoneornil(L, 3)) {
selector = lua_tointeger(L, 3);
lua_pop(L, 1); /* later we use stack[-1] to get table. */
}
lua_pushnil(L); /* nil as initial key to iterate through table */
while (lua_next(L, -2)) {
/* -1: value, -2: key */
if (!lua_isstring(L, -2)) {
/* we expect string as key, ignore it if not */
debug("ignore non-string key in table.\n");
lua_pop(L, 1);
continue;
}
luavgl_obj_set_style_kv(L, obj, selector);
lua_pop(L, 1); /* remove value, keep the key to continue. */
}
return 0;
}
/**
* obj:add_style(style, 0)
*/
static int luavgl_obj_add_style(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
luavgl_style_t *s = luavgl_check_style(L, 2);
int selector = 0;
if (!lua_isnoneornil(L, 3)) {
selector = lua_tointeger(L, 3);
}
lv_obj_add_style(obj, &s->style, selector);
return 0;
}
/**
* obj:remove_style(style, 0)
*/
static int luavgl_obj_remove_style(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
luavgl_style_t *s = luavgl_check_style(L, 2);
int selector = 0;
if (!lua_isnoneornil(L, 3)) {
selector = lua_tointeger(L, 3);
}
lv_obj_remove_style(obj, &s->style, selector);
return 0;
}
/**
* obj:remove_style_all()
*/
static int luavgl_obj_remove_style_all(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_remove_style_all(obj);
return 0;
}
static const luaL_Reg luavgl_style_methods[] = {
{"set", luavgl_style_set },
{"delete", luavgl_style_delete },
{"remove_prop", luavgl_style_remove_prop},
{NULL, NULL }
};
static void luavgl_style_init(lua_State *L)
{
luaL_newmetatable(L, "lv_style");
lua_pushcfunction(L, luavgl_style_gc);
lua_setfield(L, -2, "__gc");
luaL_newlib(L, luavgl_style_methods); /* methods belong to this type */
lua_setfield(L, -2, "__index");
lua_pop(L, 1); /* pop __index table */
}