From 7977e8e694a2d68b0796de0862e716679c448eba Mon Sep 17 00:00:00 2001 From: philmoz Date: Mon, 26 May 2025 10:35:53 +1000 Subject: [PATCH] feat(color): additions/fixes for Lua LVGL API (#6294) --- radio/src/gui/colorlcd/libui/choice.cpp | 31 +- radio/src/gui/colorlcd/libui/choice.h | 4 + radio/src/gui/colorlcd/libui/filechoice.cpp | 3 +- radio/src/gui/colorlcd/libui/filechoice.h | 1 - radio/src/lua/api_colorlcd_lvgl.cpp | 18 + radio/src/lua/lua_lvgl_widget.cpp | 423 +++++++++++--------- radio/src/lua/lua_lvgl_widget.h | 226 +++++++---- 7 files changed, 431 insertions(+), 275 deletions(-) diff --git a/radio/src/gui/colorlcd/libui/choice.cpp b/radio/src/gui/colorlcd/libui/choice.cpp index 431c3e6ff..22cadec08 100644 --- a/radio/src/gui/colorlcd/libui/choice.cpp +++ b/radio/src/gui/colorlcd/libui/choice.cpp @@ -71,12 +71,18 @@ ChoiceBase::ChoiceBase(Window* parent, const rect_t& rect, etx_font(label, FONT_XS_INDEX, LV_STATE_USER_1); } +void ChoiceBase::checkEvents() +{ + update(); + Window::checkEvents(); +} + std::string Choice::getLabelText() { std::string text; - if (_getValue) { - int val = _getValue(); + if (currentValue != INT_MAX) { + int val = currentValue; if (textHandler) { text = textHandler(val); } else { @@ -94,15 +100,20 @@ std::string Choice::getLabelText() void ChoiceBase::update() { - if (!deleted()) { - if (width() > 0) { - int w = width() - (type == CHOICE_TYPE_DROPOWN ? ICON_W - 2 : ICON_W) - PAD_TINY * 3; - if (getTextWidth(getLabelText().c_str(), 0, FONT(STD)) > w) - lv_obj_add_state(label, LV_STATE_USER_1); - else - lv_obj_clear_state(label, LV_STATE_USER_1); + if (!deleted() && _getValue) { + int v = _getValue(); + if (v != currentValue) { + currentValue = v; + std::string s = getLabelText(); + if (width() > 0) { + int w = width() - (type == CHOICE_TYPE_DROPOWN ? ICON_W - 2 : ICON_W) - PAD_TINY * 3; + if (getTextWidth(s.c_str(), 0, FONT(STD)) > w) + lv_obj_add_state(label, LV_STATE_USER_1); + else + lv_obj_clear_state(label, LV_STATE_USER_1); + } + lv_label_set_text(label, s.c_str()); } - lv_label_set_text(label, getLabelText().c_str()); } } diff --git a/radio/src/gui/colorlcd/libui/choice.h b/radio/src/gui/colorlcd/libui/choice.h index 2fb78a3fb..4a8862c64 100644 --- a/radio/src/gui/colorlcd/libui/choice.h +++ b/radio/src/gui/colorlcd/libui/choice.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include "form.h" @@ -60,11 +61,14 @@ class ChoiceBase : public FormField int vmax = 0; const char *menuTitle = nullptr; ChoiceType type; + int currentValue = INT_MAX; std::function _getValue; std::function _setValue; std::function textHandler; virtual std::string getLabelText() = 0; + + void checkEvents() override; }; class Choice : public ChoiceBase diff --git a/radio/src/gui/colorlcd/libui/filechoice.cpp b/radio/src/gui/colorlcd/libui/filechoice.cpp index 80db07da6..609cc2a55 100644 --- a/radio/src/gui/colorlcd/libui/filechoice.cpp +++ b/radio/src/gui/colorlcd/libui/filechoice.cpp @@ -99,12 +99,11 @@ FileChoice::FileChoice(Window *parent, const rect_t &rect, std::string folder, bool stripExtension, const char *title) : Choice( parent, rect, 0, 0, [=]() { return selectedIdx; }, - [=](int val) { setValue(getString(val)); }, title, CHOICE_TYPE_FOLDER), + [=](int val) { setValue(getString(val)); selectedIdx = val; }, title, CHOICE_TYPE_FOLDER), folder(std::move(folder)), extension(extension), maxlen(maxlen), getValue(std::move(getValue)), - setValue(std::move(setValue)), stripExtension(stripExtension) { update(); diff --git a/radio/src/gui/colorlcd/libui/filechoice.h b/radio/src/gui/colorlcd/libui/filechoice.h index 45ced27ed..416a1be8f 100644 --- a/radio/src/gui/colorlcd/libui/filechoice.h +++ b/radio/src/gui/colorlcd/libui/filechoice.h @@ -45,7 +45,6 @@ protected: const char* extension; int maxlen; std::function getValue; - std::function setValue; bool stripExtension; void loadFiles(); diff --git a/radio/src/lua/api_colorlcd_lvgl.cpp b/radio/src/lua/api_colorlcd_lvgl.cpp index b7b804e78..c7147fd1e 100644 --- a/radio/src/lua/api_colorlcd_lvgl.cpp +++ b/radio/src/lua/api_colorlcd_lvgl.cpp @@ -326,6 +326,17 @@ static int luaLvglGetContext(lua_State *L) return 1; } +static int luaLvglGetScrollPos(lua_State *L) +{ + auto p = LvglWidgetObjectBase::checkLvgl(L, 1, true); + if (p) { + lua_pushinteger(L, p->getScrollX()); + lua_pushinteger(L, p->getScrollY()); + return 2; + } + return 0; +} + // lvgl functions LROT_BEGIN(lvgllib, NULL, 0) LROT_FUNCENTRY(clear, luaLvglClear) @@ -377,6 +388,7 @@ LROT_BEGIN(lvgllib, NULL, 0) LROT_FUNCENTRY(enable, luaLvglEnable) LROT_FUNCENTRY(disable, luaLvglDisable) LROT_FUNCENTRY(close, luaLvglClose) + LROT_FUNCENTRY(getScrollPos, luaLvglGetScrollPos) LROT_NUMENTRY(FLOW_ROW, LV_FLEX_FLOW_ROW) LROT_NUMENTRY(FLOW_COLUMN, LV_FLEX_FLOW_COLUMN) LROT_NUMENTRY(PAD_TINY, PAD_TINY) @@ -407,6 +419,10 @@ LROT_BEGIN(lvgllib, NULL, 0) LROT_NUMENTRY(SW_TELEM, SW_TELEM) LROT_NUMENTRY(SW_OTHER, SW_OTHER) LROT_NUMENTRY(SW_CLEAR, SW_NONE) + LROT_NUMENTRY(SCROLL_OFF, LV_DIR_NONE) + LROT_NUMENTRY(SCROLL_HOR, LV_DIR_HOR) + LROT_NUMENTRY(SCROLL_VER, LV_DIR_VER) + LROT_NUMENTRY(SCROLL_ALL, LV_DIR_ALL) LROT_END(lvgllib, NULL, 0) // Metatable for simple objects (line, arc, label) @@ -417,6 +433,7 @@ LROT_BEGIN(lvgl_base_mt, NULL, LROT_MASK_GC_INDEX) LROT_FUNCENTRY(set, luaLvglSet) LROT_FUNCENTRY(show, luaLvglShow) LROT_FUNCENTRY(hide, luaLvglHide) + LROT_FUNCENTRY(getScrollPos, luaLvglGetScrollPos) LROT_END(lvgl_base_mt, NULL, LROT_MASK_GC_INDEX) // Metatable for complex objects @@ -462,6 +479,7 @@ LROT_BEGIN(lvgl_mt, NULL, LROT_MASK_GC_INDEX) LROT_FUNCENTRY(enable, luaLvglEnable) LROT_FUNCENTRY(disable, luaLvglDisable) LROT_FUNCENTRY(close, luaLvglClose) + LROT_FUNCENTRY(getScrollPos, luaLvglGetScrollPos) LROT_END(lvgl_mt, NULL, LROT_MASK_GC_INDEX) extern "C" { diff --git a/radio/src/lua/lua_lvgl_widget.cpp b/radio/src/lua/lua_lvgl_widget.cpp index d083fd254..0942fdcf6 100644 --- a/radio/src/lua/lua_lvgl_widget.cpp +++ b/radio/src/lua/lua_lvgl_widget.cpp @@ -32,6 +32,15 @@ //----------------------------------------------------------------------------- +static void clearRef(lua_State *L, int& ref) +{ + if (ref != LUA_REFNIL) + luaL_unref(L, LUA_REGISTRYINDEX, ref); + ref = LUA_REFNIL; +} + +//----------------------------------------------------------------------------- + void LvglParamFuncOrValue::parse(lua_State *L, ParamType typ) { if (lua_isfunction(L, -1)) { @@ -75,6 +84,111 @@ bool LvglParamFuncOrValue::changedValue(uint32_t v) return false; } +void LvglParamFuncOrValue::clearRef(lua_State *L) +{ + ::clearRef(L, function); +} + +//----------------------------------------------------------------------------- + +bool LvglGetSetParams::parseGetSetParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "get")) { + getFunction = luaL_ref(L, LUA_REGISTRYINDEX); + return true; + } + if (!strcmp(key, "set")) { + setFunction = luaL_ref(L, LUA_REGISTRYINDEX); + return true; + } + return false; +} + +void LvglGetSetParams::clearGetSetRefs(lua_State *L) +{ + clearRef(L, getFunction); + clearRef(L, setFunction); +} + +bool LvglTextParams::parseTextParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "text")) { + txt.parse(L, LvglParamFuncOrValue::PTXT); + return true; + } + if (!strcmp(key, "font")) { + font.parse(L); + return true; + } + return false; +} + +void LvglTextParams::clearTextRefs(lua_State *L) +{ + txt.clearRef(L); + font.clearRef(L); +} + +bool LvglMinMaxParams::parseMinMaxParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "min")) { + min = luaL_checkinteger(L, -1); + return true; + } + if (!strcmp(key, "max")) { + max = luaL_checkinteger(L, -1); + } + return false; +} + +bool LvglTitleParam::parseTitleParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "title")) { + title = luaL_checkstring(L, -1); + return true; + } + return false; +} + +bool LvglMessageParam::parseMessageParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "message")) { + message = luaL_checkstring(L, -1); + return true; + } + return false; +} + +bool LvglRoundedParam::parseRoundedParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "rounded")) { + rounded = lua_toboolean(L, -1); + return true; + } + return false; +} + +bool LvglThicknessParam::parseThicknessParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "thickness")) { + thickness = luaL_checkunsigned(L, -1); + return true; + } + return false; +} + +bool LvglValuesParam::parseValuesParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "values")) { + luaL_checktype(L, -1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + values.push_back(lua_tostring(L, -1)); + } + return true; + } + return false; +} + //----------------------------------------------------------------------------- static int pcallcont (lua_State *L, int status, lua_KContext extra) { @@ -465,13 +579,6 @@ void LvglWidgetObjectBase::saveLvglObjectRef(int ref) lvglObjectRefs.push_back(ref); } -void LvglWidgetObjectBase::clearRef(lua_State *L, int& ref) -{ - if (ref != LUA_REFNIL) - luaL_unref(L, LUA_REGISTRYINDEX, ref); - ref = LUA_REFNIL; -} - void LvglWidgetObjectBase::clearChildRefs(lua_State *L) { for (size_t i = 0; i < lvglObjectRefs.size(); i += 1) { @@ -491,8 +598,8 @@ void LvglWidgetObjectBase::clearRefs(lua_State *L) lua_pop(L, 1); clearRef(L, luaRef); - clearRef(L, color.function); - clearRef(L, opacity.function); + color.clearRef(L); + opacity.clearRef(L); clearRef(L, getVisibleFunction); clearRef(L, getSizeFunction); clearRef(L, getPosFunction); @@ -553,13 +660,9 @@ void LvglSimpleWidgetObject::hide() void LvglWidgetLabel::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "text")) { - txt.parse(L, LvglParamFuncOrValue::PTXT); - } else if (!strcmp(key, "font")) { - font.parse(L); - } else if (!strcmp(key, "align")) { + if (!strcmp(key, "align")) { align.parse(L); - } else { + } else if (!parseTextParam(L, key)) { LvglSimpleWidgetObject::parseParam(L, key); } } @@ -585,17 +688,15 @@ bool LvglWidgetLabel::callRefs(lua_State *L) void LvglWidgetLabel::clearRefs(lua_State *L) { - clearRef(L, txt.function); - clearRef(L, font.function); - clearRef(L, align.function); + align.clearRef(L); + clearTextRefs(L); LvglSimpleWidgetObject::clearRefs(L); } void LvglWidgetLabel::setText(const char *s) { - if (lvobj && txt.changedText(s)) { + if (lvobj && txt.changedText(s)) lv_label_set_text(lvobj, txt.txt); - } } void LvglWidgetLabel::setColor(LcdFlags newColor) @@ -606,10 +707,8 @@ void LvglWidgetLabel::setColor(LcdFlags newColor) void LvglWidgetLabel::setFont(LcdFlags newFont) { - if (lvobj) { - font.flags = newFont; + if (lvobj && font.changedFont(newFont)) etx_font(lvobj, FONT_INDEX(font.flags)); - } } void LvglWidgetLabel::setAlign(LcdFlags newAlign) @@ -643,9 +742,8 @@ void LvglWidgetLabel::build(lua_State *L) void LvglWidgetLineBase::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "rounded")) { - rounded = lua_toboolean(L, -1); - } else if (!strcmp(key, "dashGap")) { + if (parseRoundedParam(L, key)) return; + if (!strcmp(key, "dashGap")) { dashGap = luaL_checkinteger(L, -1); if (dashGap < 0) dashGap = 0; } else if (!strcmp(key, "dashWidth")) { @@ -780,11 +878,9 @@ uint32_t LvglWidgetLine::getPts(lua_State* L) void LvglWidgetLine::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "thickness")) { - thickness = luaL_checkunsigned(L, -1); - } else if (!strcmp(key, "rounded")) { - rounded = lua_toboolean(L, -1); - } else if (!strcmp(key, "pts")) { + if (parseRoundedParam(L, key)) return; + if (parseThicknessParam(L, key)) return; + if (!strcmp(key, "pts")) { if (lua_isfunction(L, -1)) { getPointsFunction = luaL_ref(L, LUA_REGISTRYINDEX); } else { @@ -1234,6 +1330,25 @@ 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); + } +} + +coord_t LvglWidgetBox::getScrollX() +{ + return lv_obj_get_scroll_x(window->getLvObj()); +} + +coord_t LvglWidgetBox::getScrollY() +{ + return lv_obj_get_scroll_y(window->getLvObj()); +} + void LvglWidgetBox::build(lua_State *L) { window = @@ -1242,21 +1357,21 @@ void LvglWidgetBox::build(lua_State *L) 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 (setFlex()) lv_obj_set_flex_align(window->getLvObj(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_AROUND); + setColor(color.flags); + setOpacity(opacity.value); } //----------------------------------------------------------------------------- void LvglWidgetSetting::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "title")) { - txt = luaL_checkstring(L, -1); - } else { - LvglWidgetObject::parseParam(L, key); - } + if (parseTitleParam(L, key)) return; + LvglWidgetObject::parseParam(L, key); } void LvglWidgetSetting::build(lua_State *L) @@ -1267,19 +1382,18 @@ void LvglWidgetSetting::build(lua_State *L) auto lbl = lv_label_create(window->getLvObj()); lv_obj_align(lbl, LV_ALIGN_LEFT_MID, 0, 0); etx_txt_color(lbl, COLOR_THEME_PRIMARY1_INDEX); - lv_label_set_text(lbl, txt); + lv_label_set_text(lbl, title.c_str()); } //----------------------------------------------------------------------------- void LvglWidgetBorderedObject::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "thickness")) { - thickness = luaL_checkunsigned(L, -1); - } else if (!strcmp(key, "filled")) { + if (parseThicknessParam(L, key)) return; + if (!strcmp(key, "filled")) { filled = lua_toboolean(L, -1); } else { - LvglWidgetObject::parseParam(L, key); + LvglWidgetBox::parseParam(L, key); } } @@ -1312,20 +1426,6 @@ void LvglWidgetBorderedObject::setOpacity(uint8_t newOpa) } } -void LvglWidgetBorderedObject::build(lua_State *L) -{ - window = - new Window(lvglManager->getCurrentParent(), {x, y, w, h}, lv_obj_create); - 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 { - etx_scrollbar(window->getLvObj()); - } - setColor(color.flags); - setOpacity(opacity.value); -} - //----------------------------------------------------------------------------- void LvglWidgetRoundObject::parseParam(lua_State *L, const char *key) @@ -1346,7 +1446,7 @@ bool LvglWidgetRoundObject::callRefs(lua_State *L) void LvglWidgetRoundObject::clearRefs(lua_State *L) { - clearRef(L, radius.function); + radius.clearRef(L); LvglWidgetObject::clearRefs(L); } @@ -1404,9 +1504,8 @@ void LvglWidgetCircle::build(lua_State *L) void LvglWidgetArc::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "rounded")) { - rounded = lua_toboolean(L, -1); - } else if (!strcmp(key, "startAngle")) { + if (parseRoundedParam(L, key)) return; + if (!strcmp(key, "startAngle")) { startAngle.parse(L); } else if (!strcmp(key, "endAngle")) { endAngle.parse(L); @@ -1498,12 +1597,12 @@ bool LvglWidgetArc::callRefs(lua_State *L) void LvglWidgetArc::clearRefs(lua_State *L) { - clearRef(L, startAngle.function); - clearRef(L, endAngle.function); - clearRef(L, bgColor.function); - clearRef(L, bgOpacity.function); - clearRef(L, bgStartAngle.function); - clearRef(L, bgEndAngle.function); + startAngle.clearRef(L); + endAngle.clearRef(L); + bgColor.clearRef(L); + bgOpacity.clearRef(L); + bgStartAngle.clearRef(L); + bgEndAngle.clearRef(L); LvglWidgetRoundObject::clearRefs(L); } @@ -1565,7 +1664,7 @@ bool LvglWidgetImage::callRefs(lua_State *L) void LvglWidgetImage::clearRefs(lua_State *L) { - clearRef(L, filename.function); + filename.clearRef(L); LvglWidgetObject::clearRefs(L); } @@ -1597,17 +1696,13 @@ void LvglWidgetQRCode::build(lua_State *L) void LvglWidgetTextButtonBase::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "text")) { - txt.parse(L, LvglParamFuncOrValue::PTXT); - } else if (!strcmp(key, "font")) { - font = luaL_checkunsigned(L, -1); - } else if (!strcmp(key, "cornerRadius")) { + if (!strcmp(key, "cornerRadius")) { rounded = luaL_checkunsigned(L, -1); } else if (!strcmp(key, "textColor")) { textColor.parse(L); } else if (!strcmp(key, "press")) { pressFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else { + } else if (!parseTextParam(L, key)) { LvglWidgetObject::parseParam(L, key); } } @@ -1632,19 +1727,25 @@ bool LvglWidgetTextButtonBase::callRefs(lua_State *L) void LvglWidgetTextButtonBase::clearRefs(lua_State *L) { - clearRef(L, txt.function); - clearRef(L, textColor.function); + textColor.clearRef(L); clearRef(L, pressFunction); + clearTextRefs(L); LvglWidgetObject::clearRefs(L); } void LvglWidgetTextButtonBase::setText(const char *s) { - if (txt.changedText(s)) { + if (window && txt.changedText(s)) { ((TextButton *)window)->setText(s); } } +void LvglWidgetTextButtonBase::setFont(LcdFlags newFont) +{ + if (window && font.changedFont(newFont)) + ((TextButton*)window)->setFont(FONT_INDEX(font.flags)); +} + void LvglWidgetTextButtonBase::setSize(coord_t w, coord_t h) { if (w == LV_SIZE_CONTENT || w == 0) w = lv_obj_get_width(window->getLvObj()); @@ -1654,21 +1755,21 @@ void LvglWidgetTextButtonBase::setSize(coord_t w, coord_t h) void LvglWidgetTextButtonBase::setColor(LcdFlags newColor) { - if (color.changedColor(newColor)) { + if (window && color.changedColor(newColor)) { etx_bg_color_from_flags(window->getLvObj(), color.flags); } } void LvglWidgetTextButtonBase::setTextColor(LcdFlags newColor) { - if (textColor.changedColor(newColor)) { + if (window && textColor.changedColor(newColor)) { etx_txt_color_from_flags(window->getLvObj(), textColor.flags); } } void LvglWidgetTextButtonBase::setRounded() { - if (rounded >= 0) { + if (window && rounded >= 0) { lv_obj_remove_style(window->getLvObj(), (lv_style_t*)&styles->rounded, LV_PART_MAIN); if (rounded > 0) lv_obj_set_style_radius(window->getLvObj(), rounded, LV_PART_MAIN); @@ -1694,14 +1795,6 @@ void LvglWidgetTextButton::clearRefs(lua_State *L) LvglWidgetTextButtonBase::clearRefs(L); } -void LvglWidgetTextButton::setFont(LcdFlags font) -{ - if (window) { - this->font = font; - ((TextButton*)window)->setFont(FONT_INDEX(font)); - } -} - void LvglWidgetTextButton::setChecked(bool checked) { this->checked = checked; @@ -1721,7 +1814,7 @@ void LvglWidgetTextButton::build(lua_State *L) }); } window = btn; - setFont(font); + setFont(font.flags); setChecked(checked); setColor(color.flags); setTextColor(textColor.flags); @@ -1739,14 +1832,6 @@ void LvglWidgetMomentaryButton::parseParam(lua_State *L, const char *key) } } -void LvglWidgetMomentaryButton::setFont(LcdFlags font) -{ - if (window) { - this->font = font; - ((MomentaryButton*)window)->setFont(FONT_INDEX(font)); - } -} - void LvglWidgetMomentaryButton::clearRefs(lua_State *L) { clearRef(L, releaseFunction); @@ -1764,7 +1849,7 @@ void LvglWidgetMomentaryButton::build(lua_State *L) [=]() { pcallSimpleFunc(L, releaseFunction); }); - setFont(font); + setFont(font.flags); setColor(color.flags); setTextColor(textColor.flags); setRounded(); @@ -1774,19 +1859,14 @@ void LvglWidgetMomentaryButton::build(lua_State *L) void LvglWidgetToggleSwitch::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "get")) { - getStateFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (!strcmp(key, "set")) { - setStateFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else { + if (!parseGetSetParam(L, key)) { LvglWidgetObject::parseParam(L, key); } } void LvglWidgetToggleSwitch::clearRefs(lua_State *L) { - clearRef(L, getStateFunction); - clearRef(L, setStateFunction); + clearGetSetRefs(L); LvglWidgetObject::clearRefs(L); } @@ -1794,8 +1874,8 @@ void LvglWidgetToggleSwitch::build(lua_State *L) { window = new ToggleSwitch( lvglManager->getCurrentParent(), {x, y, 0, 0}, - [=]() { return pcallGetIntVal(L, getStateFunction); }, - [=](uint8_t val) { pcallSetIntVal(L, setStateFunction, val); }); + [=]() { return pcallGetIntVal(L, getFunction); }, + [=](uint8_t val) { pcallSetIntVal(L, setFunction, val); }); } //----------------------------------------------------------------------------- @@ -1849,26 +1929,19 @@ void LvglWidgetTextEdit::build(lua_State *L) void LvglWidgetNumberEdit::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "min")) { - min = luaL_checkinteger(L, -1); - } else if (!strcmp(key, "max")) { - max = luaL_checkinteger(L, -1); - } else if (!strcmp(key, "get")) { - getFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (!strcmp(key, "set")) { - setFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (!strcmp(key, "display")) { + if (parseMinMaxParam(L, key)) return; + + if (!strcmp(key, "display")) { dispFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else { + } else if (!parseGetSetParam(L, key)) { LvglWidgetObject::parseParam(L, key); } } void LvglWidgetNumberEdit::clearRefs(lua_State *L) { - clearRef(L, getFunction); - clearRef(L, setFunction); clearRef(L, dispFunction); + clearGetSetRefs(L); LvglWidgetObject::clearRefs(L); } @@ -1906,17 +1979,9 @@ void LvglWidgetNumberEdit::build(lua_State *L) void LvglWidgetSliderBase::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "get")) { - getValueFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (!strcmp(key, "set")) { - setValueFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (!strcmp(key, "min")) { - vmin = luaL_checkinteger(L, -1); - } else if (!strcmp(key, "max")) { - vmax = luaL_checkinteger(L, -1); - } else { - LvglWidgetObject::parseParam(L, key); - } + if (parseMinMaxParam(L, key)) return; + if (parseGetSetParam(L, key)) return; + LvglWidgetObject::parseParam(L, key); } void LvglWidgetSliderBase::setColor(LcdFlags newColor) @@ -1928,8 +1993,7 @@ void LvglWidgetSliderBase::setColor(LcdFlags newColor) void LvglWidgetSliderBase::clearRefs(lua_State *L) { - clearRef(L, getValueFunction); - clearRef(L, setValueFunction); + clearGetSetRefs(L); LvglWidgetObject::clearRefs(L); } @@ -1938,9 +2002,9 @@ void LvglWidgetSliderBase::clearRefs(lua_State *L) void LvglWidgetSlider::build(lua_State *L) { window = new Slider( - lvglManager->getCurrentParent(), w, vmin, vmax, - [=]() { return pcallGetIntVal(L, getValueFunction); }, - [=](int val) { pcallSetIntVal(L, setValueFunction, val); }); + lvglManager->getCurrentParent(), w, min, max, + [=]() { return pcallGetIntVal(L, getFunction); }, + [=](int val) { pcallSetIntVal(L, setFunction, val); }); window->setPos(x, y); setColor(color.flags); } @@ -1950,9 +2014,9 @@ void LvglWidgetSlider::build(lua_State *L) void LvglWidgetVerticalSlider::build(lua_State *L) { window = new VerticalSlider( - lvglManager->getCurrentParent(), h, vmin, vmax, - [=]() { return pcallGetIntVal(L, getValueFunction); }, - [=](int val) { pcallSetIntVal(L, setValueFunction, val); }); + lvglManager->getCurrentParent(), h, min, max, + [=]() { return pcallGetIntVal(L, getFunction); }, + [=](int val) { pcallSetIntVal(L, setFunction, val); }); window->setPos(x, y); setColor(color.flags); } @@ -1963,7 +2027,7 @@ class WidgetPage : public NavWindow, public LuaEventHandler { public: WidgetPage(Window *parent, std::function backAction, - std::string title, std::string subtitle, std::string iconFile) : + std::string title, std::string subtitle, std::string iconFile, lv_dir_t scrollDir) : NavWindow(parent, {0, 0, LCD_W, LCD_H}), backAction(std::move(backAction)) { if (iconFile.empty()) @@ -1981,6 +2045,7 @@ class WidgetPage : public NavWindow, public LuaEventHandler etx_solid_bg(lvobj); 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 defined(HARDWARE_TOUCH) @@ -2012,19 +2077,30 @@ class WidgetPage : public NavWindow, public LuaEventHandler void LvglWidgetPage::parseParam(lua_State *L, const char *key) { + if (parseTitleParam(L, key)) return; if (!strcmp(key, "back")) { backActionFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (!strcmp(key, "title")) { - title = luaL_checkstring(L, -1); } 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); } } +coord_t LvglWidgetPage::getScrollX() +{ + return lv_obj_get_scroll_x(window->getLvObj()); +} + +coord_t LvglWidgetPage::getScrollY() +{ + return lv_obj_get_scroll_y(window->getLvObj()); +} + void LvglWidgetPage::clearRefs(lua_State *L) { clearRef(L, backActionFunction); @@ -2035,7 +2111,7 @@ void LvglWidgetPage::build(lua_State *L) { auto page = new WidgetPage( lvglManager->getCurrentParent(), - [=]() { pcallSimpleFunc(L, backActionFunction); }, title, subtitle, iconFile); + [=]() { pcallSimpleFunc(L, backActionFunction); }, title, subtitle, iconFile, scrollDir); window = page->getBody(); if (setFlex()) @@ -2047,8 +2123,8 @@ void LvglWidgetPage::build(lua_State *L) class LvglDialog : public BaseDialog { public: - LvglDialog(const char* title, coord_t w, coord_t h, std::function onClose) : - BaseDialog(title, true, w, h, false), + LvglDialog(std::string title, coord_t w, coord_t h, std::function onClose) : + BaseDialog(title.c_str(), true, w, h, false), onClose(std::move(onClose)) { form->setHeight(h - EdgeTxStyles::UI_ELEMENT_HEIGHT); @@ -2068,10 +2144,9 @@ class LvglDialog : public BaseDialog void LvglWidgetDialog::parseParam(lua_State *L, const char *key) { + if (parseTitleParam(L, key)) return; if (!strcmp(key, "close")) { closeFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (!strcmp(key, "title")) { - title = luaL_checkstring(L, -1); } else { LvglWidgetObject::parseParam(L, key); } @@ -2105,11 +2180,9 @@ void LvglWidgetDialog::close() void LvglWidgetConfirmDialog::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "title")) { - title = luaL_checkstring(L, -1); - } else if (!strcmp(key, "message")) { - message = luaL_checkstring(L, -1); - } else if (!strcmp(key, "confirm")) { + if (parseTitleParam(L, key)) return; + if (parseMessageParam(L, key)) return; + if (!strcmp(key, "confirm")) { confirmFunction = luaL_ref(L, LUA_REGISTRYINDEX); } else if (!strcmp(key, "cancel")) { cancelFunction = luaL_ref(L, LUA_REGISTRYINDEX); @@ -2127,7 +2200,7 @@ void LvglWidgetConfirmDialog::clearRefs(lua_State *L) void LvglWidgetConfirmDialog::build(lua_State *L) { - window = new ConfirmDialog(title, message, + window = new ConfirmDialog(title.c_str(), message.c_str(), [=]() { pcallSimpleFunc(L, confirmFunction); }, [=]() { pcallSimpleFunc(L, cancelFunction); }); } @@ -2136,11 +2209,9 @@ void LvglWidgetConfirmDialog::build(lua_State *L) void LvglWidgetMessageDialog::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "title")) { - title = luaL_checkstring(L, -1); - } else if (!strcmp(key, "message")) { - message = luaL_checkstring(L, -1); - } else if (!strcmp(key, "details")) { + if (parseTitleParam(L, key)) return; + if (parseMessageParam(L, key)) return; + if (!strcmp(key, "details")) { details = luaL_checkstring(L, -1); } else { LvglWidgetObject::parseParam(L, key); @@ -2149,26 +2220,21 @@ void LvglWidgetMessageDialog::parseParam(lua_State *L, const char *key) void LvglWidgetMessageDialog::build(lua_State *L) { - window = new MessageDialog(title, message, details); + window = new MessageDialog(title.c_str(), message.c_str(), details); } //----------------------------------------------------------------------------- void LvglWidgetPicker::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "get")) { - getFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else if (!strcmp(key, "set")) { - setFunction = luaL_ref(L, LUA_REGISTRYINDEX); - } else { + if (!parseGetSetParam(L, key)) { LvglWidgetObject::parseParam(L, key); } } void LvglWidgetPicker::clearRefs(lua_State *L) { - clearRef(L, getFunction); - clearRef(L, setFunction); + clearGetSetRefs(L); LvglWidgetObject::clearRefs(L); } @@ -2176,14 +2242,9 @@ void LvglWidgetPicker::clearRefs(lua_State *L) void LvglWidgetChoice::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "title")) { - title = luaL_checkstring(L, -1); - } else if (!strcmp(key, "values")) { - luaL_checktype(L, -1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - values.push_back(lua_tostring(L, -1)); - } - } else if (!strcmp(key, "filter")) { + if (parseTitleParam(L, key)) return; + if (parseValuesParam(L, key)) return; + if (!strcmp(key, "filter")) { filterFunction = luaL_ref(L, LUA_REGISTRYINDEX); } else { LvglWidgetPicker::parseParam(L, key); @@ -2235,16 +2296,9 @@ void LvglWidgetChoice::build(lua_State *L) void LvglWidgetMenu::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "title")) { - title = luaL_checkstring(L, -1); - } else if (!strcmp(key, "values")) { - luaL_checktype(L, -1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - values.push_back(lua_tostring(L, -1)); - } - } else { - LvglWidgetPicker::parseParam(L, key); - } + if (parseTitleParam(L, key)) return; + if (parseValuesParam(L, key)) return; + LvglWidgetPicker::parseParam(L, key); } void LvglWidgetMenu::build(lua_State *L) @@ -2377,9 +2431,8 @@ void LvglWidgetSourcePicker::build(lua_State *L) void LvglWidgetFilePicker::parseParam(lua_State *L, const char *key) { - if (!strcmp(key, "title")) { - title = luaL_checkstring(L, -1); - } else if (!strcmp(key, "folder")) { + if (parseTitleParam(L, key)) return; + if (!strcmp(key, "folder")) { folder = luaL_checkstring(L, -1); } else if (!strcmp(key, "extension")) { extension = luaL_checkstring(L, -1); @@ -2400,7 +2453,7 @@ void LvglWidgetFilePicker::build(lua_State *L) folder, extension, maxLen, [=]() { return pcallGetStringVal(L, getFunction); }, [=](std::string val) { pcallSetStringVal(L, setFunction, val.c_str()); }, - hideExtension, title); + hideExtension, title.c_str()); window = c; } diff --git a/radio/src/lua/lua_lvgl_widget.h b/radio/src/lua/lua_lvgl_widget.h index 6f8269780..2d35eedeb 100644 --- a/radio/src/lua/lua_lvgl_widget.h +++ b/radio/src/lua/lua_lvgl_widget.h @@ -50,8 +50,105 @@ struct LvglParamFuncOrValue void parse(lua_State *L, ParamType typ = PVALUE); void forceUpdate() { currVal = -1; } bool changedColor(LcdFlags newFlags); + bool changedFont(LcdFlags newFlags) { return changedColor(newFlags);} bool changedText(const char* s); bool changedValue(uint32_t v); + void clearRef(lua_State *L); +}; + +//----------------------------------------------------------------------------- + +class LvglGetSetParams +{ + public: + LvglGetSetParams() {} + + protected: + int getFunction = LUA_REFNIL; + int setFunction = LUA_REFNIL; + + bool parseGetSetParam(lua_State *L, const char *key); + void clearGetSetRefs(lua_State *L); +}; + +class LvglTextParams +{ + public: + LvglTextParams() {} + + protected: + LvglParamFuncOrValue txt = { .function = LUA_REFNIL, .txt = ""}; + LvglParamFuncOrValue font = { .function = LUA_REFNIL, .flags = FONT(STD)}; + + bool parseTextParam(lua_State *L, const char *key); + void clearTextRefs(lua_State *L); +}; + +class LvglMinMaxParams +{ + public: + LvglMinMaxParams(int min, int max) : min(min), max(max) {} + + protected: + int min; + int max; + + bool parseMinMaxParam(lua_State *L, const char *key); +}; + +class LvglTitleParam +{ + public: + LvglTitleParam() {} + + protected: + std::string title; + + bool parseTitleParam(lua_State *L, const char *key); +}; + +class LvglMessageParam +{ + public: + LvglMessageParam() {} + + protected: + std::string message; + + bool parseMessageParam(lua_State *L, const char *key); +}; + +class LvglRoundedParam +{ + public: + LvglRoundedParam() {} + + protected: + bool rounded = false; + + bool parseRoundedParam(lua_State *L, const char *key); +}; + +class LvglThicknessParam +{ + public: + LvglThicknessParam() {} + + protected: + coord_t thickness = 1; + + bool parseThicknessParam(lua_State *L, const char *key); +}; + +class LvglValuesParam +{ + public: + LvglValuesParam() {} + + protected: + std::vector values; + + bool parseValuesParam(lua_State *L, const char *key); }; //----------------------------------------------------------------------------- @@ -76,6 +173,9 @@ class LvglWidgetObjectBase virtual void disable() {}; virtual void close() {}; + virtual coord_t getScrollX() { return 0; } + virtual coord_t getScrollY() { return 0; } + virtual void setColor(LcdFlags newColor) {} virtual void setOpacity(uint8_t newOpa) {} virtual void setPos(coord_t x, coord_t y) {} @@ -110,8 +210,6 @@ class LvglWidgetObjectBase void getParams(lua_State *L, int index); - void clearRef(lua_State *L, int& ref); - void pcallSimpleFunc(lua_State *L, int funcRef); bool pcallUpdateBool(lua_State *L, int getFuncRef, std::function update); @@ -147,7 +245,7 @@ class LvglSimpleWidgetObject : public LvglWidgetObjectBase //----------------------------------------------------------------------------- -class LvglWidgetLabel : public LvglSimpleWidgetObject +class LvglWidgetLabel : public LvglSimpleWidgetObject, public LvglTextParams { public: LvglWidgetLabel() : LvglSimpleWidgetObject() {} @@ -161,9 +259,7 @@ class LvglWidgetLabel : public LvglSimpleWidgetObject void clearRefs(lua_State *L) override; protected: - LvglParamFuncOrValue font = { .function = LUA_REFNIL, .flags = FONT(STD)}; LvglParamFuncOrValue align = { .function = LUA_REFNIL, .flags = LEFT}; - LvglParamFuncOrValue txt = { .function = LUA_REFNIL, .txt = ""}; void build(lua_State *L) override; void parseParam(lua_State *L, const char *key) override; @@ -178,7 +274,7 @@ class LvglWidgetLabel : public LvglSimpleWidgetObject //----------------------------------------------------------------------------- -class LvglWidgetLineBase : public LvglSimpleWidgetObject +class LvglWidgetLineBase : public LvglSimpleWidgetObject, public LvglRoundedParam { public: LvglWidgetLineBase() : LvglSimpleWidgetObject() {} @@ -189,7 +285,6 @@ class LvglWidgetLineBase : public LvglSimpleWidgetObject void setSize(coord_t w, coord_t h) override; protected: - bool rounded = false; int dashGap = 0; int dashWidth = 0; lv_point_t pts[2]; @@ -225,7 +320,7 @@ class LvglWidgetVLine : public LvglWidgetLineBase //----------------------------------------------------------------------------- -class LvglWidgetLine : public LvglSimpleWidgetObject +class LvglWidgetLine : public LvglSimpleWidgetObject, public LvglRoundedParam, public LvglThicknessParam { public: LvglWidgetLine(); @@ -240,8 +335,6 @@ class LvglWidgetLine : public LvglSimpleWidgetObject void clearRefs(lua_State *L) override; protected: - coord_t thickness = 1; - bool rounded = false; size_t ptCnt = 0; size_t ptAlloc = 0; lv_point_t* pts = nullptr; @@ -326,19 +419,11 @@ class LvglWidgetBox : public LvglWidgetObject public: LvglWidgetBox() : LvglWidgetObject() {} - protected: - void build(lua_State *L) override; -}; - -//----------------------------------------------------------------------------- - -class LvglWidgetSetting : public LvglWidgetObject -{ - public: - LvglWidgetSetting() : LvglWidgetObject() {} + coord_t getScrollX() override; + coord_t getScrollY() override; protected: - const char *txt = ""; + lv_dir_t scrollDir = LV_DIR_ALL; void build(lua_State *L) override; void parseParam(lua_State *L, const char *key) override; @@ -346,19 +431,30 @@ class LvglWidgetSetting : public LvglWidgetObject //----------------------------------------------------------------------------- -class LvglWidgetBorderedObject : public LvglWidgetObject +class LvglWidgetSetting : public LvglWidgetObject, public LvglTitleParam { public: - LvglWidgetBorderedObject() : LvglWidgetObject() {} + LvglWidgetSetting() : LvglWidgetObject() {} + + protected: + + void build(lua_State *L) override; + void parseParam(lua_State *L, const char *key) override; +}; + +//----------------------------------------------------------------------------- + +class LvglWidgetBorderedObject : public LvglWidgetBox, public LvglThicknessParam +{ + public: + LvglWidgetBorderedObject() : LvglWidgetBox() {} void setColor(LcdFlags newColor) override; void setOpacity(uint8_t newOpa) override; protected: - coord_t thickness = 1; bool filled = false; - void build(lua_State *L) override; void parseParam(lua_State *L, const char *key) override; }; @@ -367,7 +463,10 @@ class LvglWidgetBorderedObject : public LvglWidgetObject class LvglWidgetRoundObject : public LvglWidgetBorderedObject { public: - LvglWidgetRoundObject() : LvglWidgetBorderedObject() {} + LvglWidgetRoundObject() : LvglWidgetBorderedObject() + { + scrollDir = LV_DIR_NONE; + } void setPos(coord_t x, coord_t y) override; void setRadius(coord_t r); @@ -413,7 +512,7 @@ class LvglWidgetCircle : public LvglWidgetRoundObject //----------------------------------------------------------------------------- -class LvglWidgetArc : public LvglWidgetRoundObject +class LvglWidgetArc : public LvglWidgetRoundObject, public LvglRoundedParam { public: LvglWidgetArc() : LvglWidgetRoundObject() {} @@ -431,7 +530,6 @@ class LvglWidgetArc : public LvglWidgetRoundObject void clearRefs(lua_State *L) override; protected: - bool rounded = false; LvglParamFuncOrValue startAngle = { .function = LUA_REFNIL, .coord = 0}; LvglParamFuncOrValue endAngle = { .function = LUA_REFNIL, .coord = 360}; LvglParamFuncOrValue bgColor = { .function = LUA_REFNIL, .flags = (LcdFlags)-1}; @@ -488,7 +586,7 @@ class LvglWidgetQRCode : public LvglWidgetObject //----------------------------------------------------------------------------- -class LvglWidgetTextButtonBase : public LvglWidgetObject +class LvglWidgetTextButtonBase : public LvglWidgetObject, public LvglTextParams { public: LvglWidgetTextButtonBase() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) @@ -497,6 +595,7 @@ class LvglWidgetTextButtonBase : public LvglWidgetObject } void setText(const char *s); + void setFont(LcdFlags font); void setSize(coord_t w, coord_t h) override; void setColor(LcdFlags newColor) override; void setTextColor(LcdFlags newColor); @@ -506,8 +605,6 @@ class LvglWidgetTextButtonBase : public LvglWidgetObject void clearRefs(lua_State *L) override; protected: - LvglParamFuncOrValue txt = { .function = LUA_REFNIL, .txt = ""}; - LcdFlags font = FONT(STD); coord_t rounded = -1; LvglParamFuncOrValue textColor = { .function = LUA_REFNIL, .flags = (LcdFlags)-1}; int pressFunction = LUA_REFNIL; @@ -515,6 +612,8 @@ class LvglWidgetTextButtonBase : public LvglWidgetObject void parseParam(lua_State *L, const char *key) override; void refresh() override { + setText(txt.txt); + setFont(font.flags); setTextColor(textColor.flags); LvglWidgetObject::refresh(); } @@ -527,7 +626,6 @@ class LvglWidgetTextButton : public LvglWidgetTextButtonBase public: LvglWidgetTextButton() : LvglWidgetTextButtonBase() {} - void setFont(LcdFlags font); void setChecked(bool check); void clearRefs(lua_State *L) override; @@ -541,7 +639,7 @@ class LvglWidgetTextButton : public LvglWidgetTextButtonBase void refresh() override { setChecked(checked); - LvglWidgetObject::refresh(); + LvglWidgetTextButtonBase::refresh(); } }; @@ -552,8 +650,6 @@ class LvglWidgetMomentaryButton : public LvglWidgetTextButtonBase public: LvglWidgetMomentaryButton() : LvglWidgetTextButtonBase() {} - void setFont(LcdFlags font); - void clearRefs(lua_State *L) override; protected: @@ -565,7 +661,7 @@ class LvglWidgetMomentaryButton : public LvglWidgetTextButtonBase //----------------------------------------------------------------------------- -class LvglWidgetToggleSwitch : public LvglWidgetObject +class LvglWidgetToggleSwitch : public LvglWidgetObject, public LvglGetSetParams { public: LvglWidgetToggleSwitch() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {} @@ -573,9 +669,6 @@ class LvglWidgetToggleSwitch : public LvglWidgetObject void clearRefs(lua_State *L) override; protected: - int getStateFunction = LUA_REFNIL; - int setStateFunction = LUA_REFNIL; - void build(lua_State *L) override; void parseParam(lua_State *L, const char *key) override; }; @@ -602,18 +695,14 @@ class LvglWidgetTextEdit : public LvglWidgetObject //----------------------------------------------------------------------------- -class LvglWidgetNumberEdit : public LvglWidgetObject +class LvglWidgetNumberEdit : public LvglWidgetObject, public LvglGetSetParams, public LvglMinMaxParams { public: - LvglWidgetNumberEdit() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {} + LvglWidgetNumberEdit() : LvglWidgetObject(LVGL_SIMPLEMETATABLE), LvglMinMaxParams(-1024, 1024) {} void clearRefs(lua_State *L) override; protected: - int min = -1024, max = 1024; - - int getFunction = LUA_REFNIL; - int setFunction = LUA_REFNIL; int dispFunction = LUA_REFNIL; void build(lua_State *L) override; @@ -622,10 +711,10 @@ class LvglWidgetNumberEdit : public LvglWidgetObject //----------------------------------------------------------------------------- -class LvglWidgetSliderBase : public LvglWidgetObject +class LvglWidgetSliderBase : public LvglWidgetObject, public LvglGetSetParams, public LvglMinMaxParams { public: - LvglWidgetSliderBase() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) + LvglWidgetSliderBase() : LvglWidgetObject(LVGL_SIMPLEMETATABLE), LvglMinMaxParams(0, 100) { color.flags = -1; } @@ -635,11 +724,6 @@ class LvglWidgetSliderBase : public LvglWidgetObject void clearRefs(lua_State *L) override; protected: - int32_t vmin = 0; - int32_t vmax = 100; - int getValueFunction = LUA_REFNIL; - int setValueFunction = LUA_REFNIL; - void parseParam(lua_State *L, const char *key) override; }; @@ -667,17 +751,20 @@ class LvglWidgetVerticalSlider : public LvglWidgetSliderBase //----------------------------------------------------------------------------- -class LvglWidgetPage : public LvglWidgetObject +class LvglWidgetPage : public LvglWidgetObject, public LvglTitleParam { public: LvglWidgetPage() : LvglWidgetObject() {} void clearRefs(lua_State *L) override; + coord_t getScrollX() override; + coord_t getScrollY() override; + protected: - std::string title; std::string subtitle; std::string iconFile; + lv_dir_t scrollDir = LV_DIR_ALL; int backActionFunction = LUA_REFNIL; @@ -687,7 +774,7 @@ class LvglWidgetPage : public LvglWidgetObject //----------------------------------------------------------------------------- -class LvglWidgetDialog : public LvglWidgetObject +class LvglWidgetDialog : public LvglWidgetObject, public LvglTitleParam { public: LvglWidgetDialog() : LvglWidgetObject() {} @@ -696,7 +783,6 @@ class LvglWidgetDialog : public LvglWidgetObject void close() override; protected: - const char *title = nullptr; LvglDialog* dialog = nullptr; int closeFunction = LUA_REFNIL; @@ -707,7 +793,7 @@ class LvglWidgetDialog : public LvglWidgetObject //----------------------------------------------------------------------------- -class LvglWidgetConfirmDialog : public LvglWidgetObject +class LvglWidgetConfirmDialog : public LvglWidgetObject, public LvglTitleParam, public LvglMessageParam { public: LvglWidgetConfirmDialog() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {} @@ -715,9 +801,6 @@ class LvglWidgetConfirmDialog : public LvglWidgetObject void clearRefs(lua_State *L) override; protected: - const char *title = nullptr; - const char *message = nullptr; - int confirmFunction = LUA_REFNIL; int cancelFunction = LUA_REFNIL; @@ -727,14 +810,12 @@ class LvglWidgetConfirmDialog : public LvglWidgetObject //----------------------------------------------------------------------------- -class LvglWidgetMessageDialog : public LvglWidgetObject +class LvglWidgetMessageDialog : public LvglWidgetObject, public LvglTitleParam, public LvglMessageParam { public: LvglWidgetMessageDialog() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {} protected: - const char *title = nullptr; - const char *message = nullptr; const char *details = nullptr; void build(lua_State *L) override; @@ -743,7 +824,7 @@ class LvglWidgetMessageDialog : public LvglWidgetObject //----------------------------------------------------------------------------- -class LvglWidgetPicker : public LvglWidgetObject +class LvglWidgetPicker : public LvglWidgetObject, public LvglGetSetParams { public: LvglWidgetPicker() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {} @@ -751,15 +832,12 @@ class LvglWidgetPicker : public LvglWidgetObject void clearRefs(lua_State *L) override; protected: - int getFunction = LUA_REFNIL; - int setFunction = LUA_REFNIL; - void parseParam(lua_State *L, const char *key) override; }; //----------------------------------------------------------------------------- -class LvglWidgetChoice : public LvglWidgetPicker +class LvglWidgetChoice : public LvglWidgetPicker, public LvglTitleParam, public LvglValuesParam { public: LvglWidgetChoice() : LvglWidgetPicker() {} @@ -767,8 +845,6 @@ class LvglWidgetChoice : public LvglWidgetPicker void clearRefs(lua_State *L) override; protected: - std::string title; - std::vector values; int filterFunction = LUA_REFNIL; void build(lua_State *L) override; @@ -777,15 +853,12 @@ class LvglWidgetChoice : public LvglWidgetPicker //----------------------------------------------------------------------------- -class LvglWidgetMenu : public LvglWidgetPicker +class LvglWidgetMenu : public LvglWidgetPicker, public LvglTitleParam, public LvglValuesParam { public: LvglWidgetMenu() : LvglWidgetPicker() {} protected: - std::string title; - std::vector values; - void build(lua_State *L) override; void parseParam(lua_State *L, const char *key) override; }; @@ -864,14 +937,13 @@ class LvglWidgetSourcePicker : public LvglWidgetPicker //----------------------------------------------------------------------------- -class LvglWidgetFilePicker : public LvglWidgetPicker +class LvglWidgetFilePicker : public LvglWidgetPicker, public LvglTitleParam { public: LvglWidgetFilePicker() : LvglWidgetPicker() {} protected: - const char *title = nullptr; - const char* folder = nullptr; + const char* folder = nullptr; const char* extension = nullptr; int maxLen = 255; bool hideExtension = false;