feat(color): enhancements and fixes to the LVGL Lua API's (#6351)

This commit is contained in:
philmoz
2025-06-13 11:10:50 +10:00
committed by GitHub
parent 5c04801162
commit 3475978dd8
12 changed files with 194 additions and 77 deletions
+112 -38
View File
@@ -41,15 +41,12 @@ static void clearRef(lua_State *L, int& ref)
//-----------------------------------------------------------------------------
void LvglParamFuncOrValue::parse(lua_State *L, ParamType typ)
void LvglParamFuncOrValue::parse(lua_State *L)
{
if (lua_isfunction(L, -1)) {
function = luaL_ref(L, LUA_REGISTRYINDEX);
} else {
if (typ == PTXT)
txt = luaL_checkstring(L, -1);
else
value = luaL_checkunsigned(L, -1);
value = luaL_checkunsigned(L, -1);
}
}
@@ -63,17 +60,6 @@ bool LvglParamFuncOrValue::changedColor(LcdFlags newFlags)
return false;
}
bool LvglParamFuncOrValue::changedText(const char* s)
{
txt = s;
uint32_t h = hash(txt, strlen(txt));
if (h != currVal) {
currVal = h;
return true;
}
return false;
}
bool LvglParamFuncOrValue::changedValue(uint32_t v)
{
value = v;
@@ -89,6 +75,31 @@ void LvglParamFuncOrValue::clearRef(lua_State *L)
::clearRef(L, function);
}
void LvglParamFuncOrString::parse(lua_State *L)
{
if (lua_isfunction(L, -1)) {
function = luaL_ref(L, LUA_REGISTRYINDEX);
} else {
txt = luaL_checkstring(L, -1);
}
}
bool LvglParamFuncOrString::changedText(const char* s)
{
txt = s;
uint32_t h = hash(chars(), txt.size());
if (h != txtHash) {
txtHash = h;
return true;
}
return false;
}
void LvglParamFuncOrString::clearRef(lua_State *L)
{
::clearRef(L, function);
}
//-----------------------------------------------------------------------------
bool LvglGetSetParams::parseGetSetParam(lua_State *L, const char *key)
@@ -113,7 +124,7 @@ void LvglGetSetParams::clearGetSetRefs(lua_State *L)
bool LvglTextParams::parseTextParam(lua_State *L, const char *key)
{
if (!strcmp(key, "text")) {
txt.parse(L, LvglParamFuncOrValue::PTXT);
txt.parse(L);
return true;
}
if (!strcmp(key, "font")) {
@@ -189,6 +200,27 @@ bool LvglValuesParam::parseValuesParam(lua_State *L, const char *key)
return false;
}
bool LvglScrollableParams::parseScrollableParam(lua_State *L, const char *key)
{
if (!strcmp(key, "scrollBar")) {
showScrollBar = lua_toboolean(L, -1);
return true;
}
if (!strcmp(key, "scrollDir")) {
scrollDir = (lv_dir_t)luaL_checkunsigned(L, -1);
return true;
}
if (!strcmp(key, "scrollTo")) {
scrollToFunction = luaL_ref(L, LUA_REGISTRYINDEX);
return true;
}
if (!strcmp(key, "scrolled")) {
scrolledFunction = luaL_ref(L, LUA_REGISTRYINDEX);
return true;
}
return false;
}
//-----------------------------------------------------------------------------
static int pcallcont (lua_State *L, int status, lua_KContext extra) {
@@ -214,6 +246,17 @@ static bool pcallFuncWithInt(lua_State *L, int funcRef, int nretval, int val)
return false;
}
static bool pcallFuncWith2Int(lua_State *L, int funcRef, int nretval, int val1, int val2)
{
if (funcRef != LUA_REFNIL) {
lua_rawgeti(L, LUA_REGISTRYINDEX, funcRef);
lua_pushinteger(L, val1);
lua_pushinteger(L, val2);
return lua_pcallk(L, 2, nretval, 0, 0, pcallcont) == LUA_OK;
}
return false;
}
static bool pcallFuncWithString(lua_State *L, int funcRef, int nretval, const char* val)
{
if (funcRef != LUA_REFNIL) {
@@ -696,7 +739,7 @@ void LvglWidgetLabel::clearRefs(lua_State *L)
void LvglWidgetLabel::setText(const char *s)
{
if (lvobj && txt.changedText(s))
lv_label_set_text(lvobj, txt.txt);
lv_label_set_text(lvobj, txt.chars());
}
void LvglWidgetLabel::setColor(LcdFlags newColor)
@@ -731,7 +774,7 @@ void LvglWidgetLabel::build(lua_State *L)
lvobj = lv_label_create(lvglManager->getCurrentParent()->getLvObj());
setPos(x, y);
setSize(w, h);
setText(txt.txt);
setText(txt.chars());
setColor(color.flags);
setOpacity(opacity.value);
setFont(font.flags);
@@ -869,7 +912,7 @@ uint32_t LvglWidgetLine::getPts(lua_State* L)
}
for (size_t i = 0; i < ptCnt; i += 1)
getPt(L, i);
return hash(pts, sizeof(ptCnt * sizeof(lv_point_t)));
return hash(pts, ptCnt * sizeof(lv_point_t));
} else {
ptCnt = 0;
return -1;
@@ -1332,11 +1375,8 @@ void LvglWidgetObject::clearRefs(lua_State *L)
void LvglWidgetBox::parseParam(lua_State *L, const char *key)
{
if (!strcmp(key, "scrollDir")) {
scrollDir = (lv_dir_t)luaL_checkunsigned(L, -1);
} else {
LvglWidgetObject::parseParam(L, key);
}
if (parseScrollableParam(L, key)) return;
LvglWidgetObject::parseParam(L, key);
}
coord_t LvglWidgetBox::getScrollX()
@@ -1349,16 +1389,34 @@ coord_t LvglWidgetBox::getScrollY()
return lv_obj_get_scroll_y(window->getLvObj());
}
bool LvglWidgetBox::callRefs(lua_State *L)
{
if (!pcallUpdate2Int(L, scrollToFunction,
[=](int x, int y) { if (x != getScrollX() || y != getScrollY()) lv_obj_scroll_to(window->getLvObj(), x, y, LV_ANIM_OFF); })) {
return false;
}
return LvglWidgetObject::callRefs(L);
}
void LvglWidgetBox::clearRefs(lua_State *L)
{
clearRef(L, scrollToFunction);
LvglWidgetObject::clearRefs(L);
}
void LvglWidgetBox::build(lua_State *L)
{
window =
new Window(lvglManager->getCurrentParent(), {x, y, w, h}, lv_obj_create);
window->disableForcedScroll();
window->setScrollHandler([=](coord_t x, coord_t y) { pcallFuncWith2Int(L, scrolledFunction, 0, x, y); });
lv_obj_add_flag(window->getLvObj(), LV_OBJ_FLAG_EVENT_BUBBLE);
if (luaScriptManager->isWidget()) {
lv_obj_clear_flag(window->getLvObj(), LV_OBJ_FLAG_CLICKABLE);
} else {
lv_obj_set_scroll_dir(window->getLvObj(), scrollDir);
etx_scrollbar(window->getLvObj());
if (showScrollBar)
etx_scrollbar(window->getLvObj());
}
if (setFlex())
lv_obj_set_flex_align(window->getLvObj(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_AROUND);
@@ -1637,7 +1695,7 @@ void LvglWidgetArc::build(lua_State *L)
void LvglWidgetImage::parseParam(lua_State *L, const char *key)
{
if (!strcmp(key, "file")) {
filename.parse(L, LvglParamFuncOrValue::PTXT);
filename.parse(L);
} else if (!strcmp(key, "fill")) {
fillFrame = lua_toboolean(L, -1);
} else {
@@ -1652,7 +1710,7 @@ bool LvglWidgetImage::callRefs(lua_State *L)
if (pcallFunc(L, filename.function, 1)) {
const char *s = luaL_checkstring(L, -1);
if (filename.changedText(s)) {
((StaticImage*)window)->setSource(filename.txt);
((StaticImage*)window)->setSource(filename.chars());
}
lua_settop(L, t);
} else {
@@ -1671,7 +1729,7 @@ void LvglWidgetImage::clearRefs(lua_State *L)
void LvglWidgetImage::build(lua_State *L)
{
window = new StaticImage(lvglManager->getCurrentParent(), {x, y, w, h},
filename.txt, fillFrame);
filename.chars(), fillFrame);
}
//-----------------------------------------------------------------------------
@@ -1805,7 +1863,7 @@ void LvglWidgetTextButton::build(lua_State *L)
{
if (h == LV_SIZE_CONTENT) h = 0;
auto btn =
new TextButton(lvglManager->getCurrentParent(), {x, y, w, h}, txt.txt, [=]() {
new TextButton(lvglManager->getCurrentParent(), {x, y, w, h}, txt.chars(), [=]() {
return pcallGetOptIntVal(L, pressFunction, 0);
});
if (longPressFunction != LUA_REFNIL) {
@@ -1842,7 +1900,7 @@ void LvglWidgetMomentaryButton::build(lua_State *L)
{
if (h == LV_SIZE_CONTENT) h = 0;
window =
new MomentaryButton(lvglManager->getCurrentParent(), {x, y, w, h}, txt.txt,
new MomentaryButton(lvglManager->getCurrentParent(), {x, y, w, h}, txt.chars(),
[=]() {
pcallSimpleFunc(L, pressFunction);
},
@@ -2028,7 +2086,8 @@ class WidgetPage : public NavWindow, public LuaEventHandler
{
public:
WidgetPage(Window *parent, std::function<void()> backAction,
std::string title, std::string subtitle, std::string iconFile, lv_dir_t scrollDir) :
std::string title, std::string subtitle, std::string iconFile,
lv_dir_t scrollDir, bool showScrollBar) :
NavWindow(parent, {0, 0, LCD_W, LCD_H}), backAction(std::move(backAction))
{
if (iconFile.empty())
@@ -2047,7 +2106,8 @@ class WidgetPage : public NavWindow, public LuaEventHandler
lv_obj_set_style_max_height(body->getLvObj(), LCD_H - EdgeTxStyles::MENU_HEADER_HEIGHT,
LV_PART_MAIN);
lv_obj_set_scroll_dir(body->getLvObj(), scrollDir);
etx_scrollbar(body->getLvObj());
if (showScrollBar)
etx_scrollbar(body->getLvObj());
#if defined(HARDWARE_TOUCH)
addBackButton();
@@ -2079,14 +2139,13 @@ class WidgetPage : public NavWindow, public LuaEventHandler
void LvglWidgetPage::parseParam(lua_State *L, const char *key)
{
if (parseTitleParam(L, key)) return;
if (parseScrollableParam(L, key)) return;
if (!strcmp(key, "back")) {
backActionFunction = luaL_ref(L, LUA_REGISTRYINDEX);
} else if (!strcmp(key, "subtitle")) {
subtitle = luaL_checkstring(L, -1);
} else if (!strcmp(key, "icon")) {
iconFile = luaL_checkstring(L, -1);
} else if (!strcmp(key, "scrollDir")) {
scrollDir = (lv_dir_t)luaL_checkunsigned(L, -1);
} else {
LvglWidgetObject::parseParam(L, key);
}
@@ -2102,6 +2161,15 @@ coord_t LvglWidgetPage::getScrollY()
return lv_obj_get_scroll_y(window->getLvObj());
}
bool LvglWidgetPage::callRefs(lua_State *L)
{
if (!pcallUpdate2Int(L, scrollToFunction,
[=](int x, int y) { if (x != getScrollX() || y != getScrollY()) lv_obj_scroll_to(window->getLvObj(), x, y, LV_ANIM_OFF); })) {
return false;
}
return LvglWidgetObject::callRefs(L);
}
void LvglWidgetPage::clearRefs(lua_State *L)
{
clearRef(L, backActionFunction);
@@ -2112,9 +2180,11 @@ void LvglWidgetPage::build(lua_State *L)
{
auto page = new WidgetPage(
lvglManager->getCurrentParent(),
[=]() { pcallSimpleFunc(L, backActionFunction); }, title, subtitle, iconFile, scrollDir);
[=]() { pcallSimpleFunc(L, backActionFunction); }, title, subtitle, iconFile, scrollDir, showScrollBar);
window = page->getBody();
window->disableForcedScroll();
window->setScrollHandler([=](coord_t x, coord_t y) { pcallFuncWith2Int(L, scrolledFunction, 0, x, y); });
if (setFlex())
lv_obj_set_flex_align(window->getLvObj(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_SPACE_AROUND);
}
@@ -2221,7 +2291,7 @@ void LvglWidgetMessageDialog::parseParam(lua_State *L, const char *key)
void LvglWidgetMessageDialog::build(lua_State *L)
{
window = new MessageDialog(title.c_str(), message.c_str(), details);
window = new MessageDialog(title.c_str(), message.c_str(), details.c_str());
}
//-----------------------------------------------------------------------------
@@ -2247,6 +2317,8 @@ void LvglWidgetChoice::parseParam(lua_State *L, const char *key)
if (parseValuesParam(L, key)) return;
if (!strcmp(key, "filter")) {
filterFunction = luaL_ref(L, LUA_REGISTRYINDEX);
} else if (!strcmp(key, "popupWidth")) {
popupWidth = luaL_checkinteger(L, -1);
} else {
LvglWidgetPicker::parseParam(L, key);
}
@@ -2266,6 +2338,8 @@ void LvglWidgetChoice::build(lua_State *L)
[=]() { return pcallGetIntVal(L, getFunction) - 1; },
[=](int val) { pcallSetIntVal(L, setFunction, val + 1); }, title.c_str());
c->setPopupWidth(popupWidth);
if (filterFunction != LUA_REFNIL)
c->setAvailableHandler([=](int n) {
bool rv = true;
@@ -2451,7 +2525,7 @@ void LvglWidgetFilePicker::build(lua_State *L)
if (h == LV_SIZE_CONTENT) h = 0;
auto c = new FileChoice(
lvglManager->getCurrentParent(), {x, y, w, h},
folder, extension, maxLen,
folder.c_str(), extension.c_str(), maxLen,
[=]() { return pcallGetStringVal(L, getFunction); },
[=](std::string val) { pcallSetStringVal(L, setFunction, val.c_str()); },
hideExtension, title.c_str());