feat(color): add Slider & Choice widget option types (#5518)

This commit is contained in:
philmoz
2024-09-11 16:20:37 +10:00
committed by GitHub
parent c3ed4c1f1b
commit ecfa1e1b5b
38 changed files with 165 additions and 258 deletions
+18 -85
View File
@@ -71,76 +71,6 @@ static int luaLvglObjEx(lua_State *L, std::function<LvglWidgetObject*()> create,
return 1;
}
static int luaLvglLabel(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetLabel(); });
}
static int luaLvglRectangle(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetRectangle(); });
}
static int luaLvglCircle(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetCircle(); });
}
static int luaLvglArc(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetArc(); });
}
static int luaLvglImage(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetImage(); });
}
static int luaLvglQRCode(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetQRCode(); });
}
// static int luaLvglMeter(lua_State *L)
// {
// return luaLvglObjEx(L, [=]() { return new LvglWidgetMeter(); });
// }
static int luaLvglButton(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetTextButton(); }, true);
}
static int luaLvglToggle(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetToggleSwitch(); }, true);
}
static int luaLvglTextEdit(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetTextEdit(); }, true);
}
static int luaLvglNumberEdit(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetNumberEdit(); }, true);
}
static int luaLvglChoice(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetChoice(); }, true);
}
static int luaLvglSlider(lua_State *L)
{
return luaLvglObjEx(L, [=]() { return new LvglWidgetSlider(); }, true);
}
static int luaLvglPage(lua_State *L)
{
return luaLvglObj(L, [=]() { return new LvglWidgetPage(); }, true);
}
static int luaLvglConfirm(lua_State *L)
{
auto obj = new LvglWidgetConfirmDialog();
@@ -316,22 +246,25 @@ LROT_FUNCENTRY(__gc, luaDestroyLvglWidget)
LROT_TABENTRY(__index, lvgllib)
LROT_FUNCENTRY(clear, luaLvglClear)
LROT_FUNCENTRY(build, luaLvglBuild)
// Objects
LROT_FUNCENTRY(label, luaLvglLabel)
LROT_FUNCENTRY(rectangle, luaLvglRectangle)
LROT_FUNCENTRY(circle, luaLvglCircle)
LROT_FUNCENTRY(arc, luaLvglArc)
LROT_FUNCENTRY(image, luaLvglImage)
LROT_FUNCENTRY(qrcode, luaLvglQRCode)
// LROT_FUNCENTRY(meter, luaLvglMeter)
LROT_FUNCENTRY(button, luaLvglButton)
LROT_FUNCENTRY(toggle, luaLvglToggle)
// Objects - widgets and standalone
LROT_FUNCENTRY(label, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetLabel(); }); })
LROT_FUNCENTRY(rectangle, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetRectangle(); }); })
LROT_FUNCENTRY(circle, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetCircle(); }); })
LROT_FUNCENTRY(arc, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetArc(); }); })
LROT_FUNCENTRY(image, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetImage(); }); })
LROT_FUNCENTRY(qrcode, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetQRCode(); }); })
// LROT_FUNCENTRY(meter, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetMeter(); }); })
// Objects - standalone scripts only
LROT_FUNCENTRY(button, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetTextButton(); }, true); })
LROT_FUNCENTRY(toggle, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetToggleSwitch(); }, true); })
LROT_FUNCENTRY(textEdit, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetTextEdit(); }, true); })
LROT_FUNCENTRY(numberEdit, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetNumberEdit(); }, true); })
LROT_FUNCENTRY(choice, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetChoice(); }, true); })
LROT_FUNCENTRY(slider, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetSlider(); }, true); })
// Containers
LROT_FUNCENTRY(page, [](lua_State* L) { return luaLvglObj(L, []() { return new LvglWidgetPage(); }, true); })
// Dialogs
LROT_FUNCENTRY(confirm, luaLvglConfirm)
LROT_FUNCENTRY(textEdit, luaLvglTextEdit)
LROT_FUNCENTRY(numberEdit, luaLvglNumberEdit)
LROT_FUNCENTRY(choice, luaLvglChoice)
LROT_FUNCENTRY(slider, luaLvglSlider)
LROT_FUNCENTRY(page, luaLvglPage)
// Manipulation functions
LROT_FUNCENTRY(set, luaLvglSet)
LROT_FUNCENTRY(show, luaLvglShow)
+8 -6
View File
@@ -3018,26 +3018,24 @@ LROT_BEGIN(etxcst, NULL, 0)
// Constants
LROT_NUMENTRY( FULLSCALE, RESX )
#if defined(COLORLCD)
LROT_NUMENTRY( STDSIZE, FONT(STD) )
LROT_NUMENTRY( XXLSIZE, FONT(XXL) )
LROT_NUMENTRY( DBLSIZE, FONT(XL) )
LROT_NUMENTRY( MIDSIZE, FONT(L) )
LROT_NUMENTRY( SMLSIZE, FONT(XS) )
LROT_NUMENTRY( TINSIZE, FONT(XXS) )
LROT_NUMENTRY( STDBOLD, FONT(BOLD) )
LROT_NUMENTRY( BLINK, BLINK )
LROT_NUMENTRY( INVERS, INVERS )
LROT_NUMENTRY( VCENTER, VCENTERED )
#else
LROT_NUMENTRY( XXLSIZE, XXLSIZE )
LROT_NUMENTRY( DBLSIZE, DBLSIZE )
LROT_NUMENTRY( MIDSIZE, MIDSIZE )
LROT_NUMENTRY( SMLSIZE, SMLSIZE )
LROT_NUMENTRY( BOLD, BOLD )
LROT_NUMENTRY( BLINK, BLINK )
LROT_NUMENTRY( INVERS, INVERS )
#endif
#if defined(COLORLCD)
LROT_NUMENTRY( BOLD, FONT(BOLD) )
LROT_NUMENTRY( VCENTER, VCENTERED )
#else
LROT_NUMENTRY( BOLD, BOLD )
#endif
LROT_NUMENTRY( RIGHT, RIGHT )
LROT_NUMENTRY( LEFT, LEFT )
@@ -3113,6 +3111,10 @@ LROT_BEGIN(etxcst, NULL, 0)
LROT_NUMENTRY( TEXT_SIZE, ZoneOption::TextSize )
LROT_NUMENTRY( ALIGNMENT, ZoneOption::Align )
LROT_NUMENTRY( SWITCH, ZoneOption::Switch )
LROT_NUMENTRY( INTVAL, ZoneOption::Integer )
LROT_NUMENTRY( SRCVAL, ZoneOption::Source )
LROT_NUMENTRY( SLIDER, ZoneOption::Slider )
LROT_NUMENTRY( CHOICE, ZoneOption::Choice )
LROT_NUMENTRY( MENU_HEADER_HEIGHT, COLOR2FLAGS(EdgeTxStyles::MENU_HEADER_HEIGHT) )
// Colors gui/colorlcd/colors.h
+14
View File
@@ -1418,3 +1418,17 @@ bool isRadioScriptTool(const char * filename)
const char * ext = getFileExtension(filename);
return ext && !strcasecmp(ext, SCRIPT_EXT);
}
void l_pushtableint(lua_State* ls, const char * key, int value)
{
lua_pushstring(ls, key);
lua_pushinteger(ls, value);
lua_settable(ls, -3);
}
void l_pushtablebool(lua_State* ls, const char * key, bool value)
{
lua_pushstring(ls, key);
lua_pushboolean(ls, value);
lua_settable(ls, -3);
}
+2
View File
@@ -248,6 +248,8 @@ struct LuaMemTracer {
void * tracer_alloc(void * ud, void * ptr, size_t osize, size_t nsize);
void l_pushtableint(lua_State* ls, const char * key, int value);
void l_pushtablebool(lua_State* ls, const char * key, bool value);
#else // defined(LUA)
+1 -15
View File
@@ -20,12 +20,12 @@
*/
#include "lua_event.h"
#include "lua_api.h"
#include "edgetx_helpers.h"
#include "board_common.h"
#include "timers_driver.h"
#include "keys.h"
extern "C" {
#include "lua.h"
};
@@ -83,20 +83,6 @@ LuaEventData* luaGetEventSlot(event_t event)
static tmr10ms_t _swipeTimeOut = 0;
static void l_pushtableint(lua_State* ls, const char * key, int value)
{
lua_pushstring(ls, key);
lua_pushinteger(ls, value);
lua_settable(ls, -3);
}
static void l_pushtablebool(lua_State* ls, const char * key, bool value)
{
lua_pushstring(ls, key);
lua_pushboolean(ls, value);
lua_settable(ls, -3);
}
void luaPushTouchEventTable(lua_State* ls, LuaEventData* evt)
{
lua_newtable(ls);
+1 -1
View File
@@ -50,7 +50,7 @@ void LvglWidgetObjectBase::pcallSimpleFunc(lua_State *L, int funcRef)
if (funcRef) {
PROTECT_LUA()
{
if (!pcallFunc(L, funcRef, 1)) {
if (!pcallFunc(L, funcRef, 0)) {
lvglManager->luaShowError();
}
}
+21 -24
View File
@@ -219,9 +219,9 @@ void LuaWidget::redraw_cb(lv_event_t* e)
LuaWidget::LuaWidget(const WidgetFactory* factory, Window* parent,
const rect_t& rect, WidgetPersistentData* persistentData,
int luaWidgetDataRef, int zoneRectDataRef) :
int luaWidgetDataRef, int zoneRectDataRef, int optionsDataRef) :
Widget(factory, parent, rect, persistentData),
zoneRectDataRef(zoneRectDataRef),
zoneRectDataRef(zoneRectDataRef), optionsDataRef(optionsDataRef),
errorMessage(nullptr)
{
this->luaWidgetDataRef = luaWidgetDataRef;
@@ -304,13 +304,6 @@ void LuaWidget::checkEvents()
#endif
}
static void l_pushtableint(const char* key, int value)
{
lua_pushstring(lsWidgets, key);
lua_pushinteger(lsWidgets, value);
lua_settable(lsWidgets, -3);
}
void LuaWidget::update()
{
Widget::update();
@@ -321,24 +314,28 @@ void LuaWidget::update()
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaFactory()->updateFunction);
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaWidgetDataRef);
lua_newtable(lsWidgets);
// Get options table and update values
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, optionsDataRef);
int i = 0;
for (const ZoneOption* option = getOptions(); option->name; option++, i++) {
if (option->type == ZoneOption::String) {
lua_pushstring(lsWidgets, option->name);
char str[LEN_ZONE_OPTION_STRING + 1] = {
0}; // Zero-terminated string for Lua
strncpy(str, persistentData->options[i].value.stringValue,
LEN_ZONE_OPTION_STRING);
lua_pushstring(lsWidgets, &str[0]);
lua_settable(lsWidgets, -3);
} else if (option->type == ZoneOption::Color) {
int32_t value = persistentData->options[i].value.unsignedValue;
l_pushtableint(option->name, value);
} else {
int32_t value = persistentData->options[i].value.signedValue;
l_pushtableint(option->name, value);
auto optVal = getOptionValue(i);
switch (option->type) {
case ZoneOption::String:
{
char str[LEN_ZONE_OPTION_STRING + 1] = {0};
strncpy(str, optVal->stringValue, LEN_ZONE_OPTION_STRING);
lua_pushstring(lsWidgets, str);
}
break;
case ZoneOption::Integer:
case ZoneOption::Switch:
lua_pushinteger(lsWidgets, optVal->signedValue);
break;
default:
lua_pushinteger(lsWidgets, optVal->unsignedValue);
break;
}
lua_setfield(lsWidgets, -2, option->name);
}
if (useLvglLayout()) luaLvglManager = this;
+3 -1
View File
@@ -93,6 +93,7 @@ class LuaWidget : public Widget, public LuaEventHandler, public LuaLvglManager
friend class LuaWidgetFactory;
int zoneRectDataRef;
int optionsDataRef;
char* errorMessage;
bool refreshed = false;
@@ -112,7 +113,8 @@ class LuaWidget : public Widget, public LuaEventHandler, public LuaLvglManager
public:
LuaWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect,
WidgetPersistentData* persistentData, int luaWidgetDataRef, int zoneRectDataRef);
WidgetPersistentData* persistentData, int luaWidgetDataRef, int zoneRectDataRef,
int optionsDataRef);
~LuaWidget() override;
#if defined(DEBUG_WINDOWS)
+16 -19
View File
@@ -26,13 +26,6 @@
#define MAX_INSTRUCTIONS (20000/100)
static void l_pushtableint(const char * key, int value)
{
lua_pushstring(lsWidgets, key);
lua_pushinteger(lsWidgets, value);
lua_settable(lsWidgets, -3);
}
LuaWidgetFactory::LuaWidgetFactory(const char* name, ZoneOption* widgetOptions,
int createFunction) :
WidgetFactory(name, widgetOptions),
@@ -72,18 +65,19 @@ Widget* LuaWidgetFactory::create(Window* parent, const rect_t& rect,
// Make 'zone' table for 'create' call
lua_newtable(lsWidgets);
l_pushtableint("x", 0);
l_pushtableint("y", 0);
l_pushtableint("w", rect.w);
l_pushtableint("h", rect.h);
l_pushtableint("xabs", rect.x);
l_pushtableint("yabs", rect.y);
l_pushtableint(lsWidgets, "x", 0);
l_pushtableint(lsWidgets, "y", 0);
l_pushtableint(lsWidgets, "w", rect.w);
l_pushtableint(lsWidgets, "h", rect.h);
l_pushtableint(lsWidgets, "xabs", rect.x);
l_pushtableint(lsWidgets, "yabs", rect.y);
// Store the zone data in registry for later updates
int zoneRectDataRef = luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
// Push stored zone for 'create' call
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, zoneRectDataRef);
// Create options table
lua_newtable(lsWidgets);
int i = 0;
for (const ZoneOption* option = options; option->name; option++, i++) {
@@ -95,18 +89,21 @@ Widget* LuaWidgetFactory::create(Window* parent, const rect_t& rect,
LEN_ZONE_OPTION_STRING);
lua_pushstring(lsWidgets, &str[0]);
lua_settable(lsWidgets, -3);
} else if (option->type == ZoneOption::Color) {
int32_t value = persistentData->options[i].value.unsignedValue;
l_pushtableint(option->name, value);
} else if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch) {
l_pushtableint(lsWidgets, option->name, persistentData->options[i].value.signedValue);
} else {
int32_t value = persistentData->options[i].value.signedValue;
l_pushtableint(option->name, value);
l_pushtableint(lsWidgets, option->name, persistentData->options[i].value.unsignedValue);
}
}
// Store the options data in registry for later updates
int optionsDataRef = luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
// Push stored options for 'create' call
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, optionsDataRef);
bool err = lua_pcall(lsWidgets, 2, 1, 0);
int widgetData = err ? LUA_NOREF : luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
LuaWidget* lw = new LuaWidget(this, parent, rect, persistentData, widgetData, zoneRectDataRef);
LuaWidget* lw = new LuaWidget(this, parent, rect, persistentData, widgetData, zoneRectDataRef, optionsDataRef);
if (err) lw->setErrorMessage("create()");
return lw;
}
+16 -31
View File
@@ -114,7 +114,7 @@ ZoneOption *createOptionsArray(int reference, uint8_t maxOptions)
// TRACE("limited to %d options", count);
}
ZoneOption *options = (ZoneOption *)malloc(sizeof(ZoneOption) * (count + 1));
ZoneOption *options = new ZoneOption[count + 1];
if (!options) {
return NULL;
}
@@ -131,82 +131,67 @@ ZoneOption *createOptionsArray(int reference, uint8_t maxOptions)
uint8_t field = 0;
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2) && field < 5;
lua_pop(lsWidgets, 1), field++) {
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
switch (field) {
case 0:
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TSTRING); // value is string
option->name = lua_tostring(lsWidgets, -1);
option->displayName = nullptr;
// TRACE("name = %s", option->name);
break;
case 1:
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->type = (ZoneOption::Type)lua_tointeger(lsWidgets, -1);
// TRACE("type = %d", option->type);
if (option->type > ZoneOption::Color) {
// wrong type
option->type = ZoneOption::Integer;
}
option->deflt.unsignedValue = 0;
if (option->type == ZoneOption::Integer) {
// set some sensible defaults
option->deflt.signedValue = 0;
option->min.signedValue = -100;
option->max.signedValue = 100;
} else if (option->type == ZoneOption::Switch) {
// set some sensible defaults
option->deflt.signedValue = SWSRC_NONE;
option->min.signedValue = SWSRC_FIRST;
option->max.signedValue = SWSRC_LAST;
} else if (option->type == ZoneOption::Timer) {
option->deflt.unsignedValue = 0;
option->min.unsignedValue = 0;
option->max.unsignedValue = MAX_TIMERS - 1;
} else if (option->type == ZoneOption::TextSize) {
option->deflt.unsignedValue = FONT_STD_INDEX;
option->min.unsignedValue = FONT_STD_INDEX;
option->max.unsignedValue = FONTS_COUNT - 1;
} else if (option->type == ZoneOption::String) {
option->deflt.stringValue[0] = 0;
} else if (option->type == ZoneOption::Slider) {
option->min.unsignedValue = 0;
option->max.unsignedValue = 9;
}
break;
case 2:
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.signedValue = lua_tointeger(lsWidgets, -1);
// TRACE("default signed = %d", option->deflt.signedValue);
} else if (option->type == ZoneOption::Source ||
option->type == ZoneOption::TextSize ||
option->type == ZoneOption::Timer ||
option->type == ZoneOption::Align) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.unsignedValue = lua_tounsigned(lsWidgets, -1);
// TRACE("default unsigned = %u", option->deflt.unsignedValue);
} else if (option->type == ZoneOption::Color) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.unsignedValue = lua_tounsigned(lsWidgets, -1);
// TRACE("default unsigned = %u", option->deflt.unsignedValue);
} else if (option->type == ZoneOption::Bool) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.boolValue = (lua_tounsigned(lsWidgets, -1) != 0);
// TRACE("default bool = %d", (int)(option->deflt.boolValue));
} else if (option->type == ZoneOption::String) {
strncpy(option->deflt.stringValue, lua_tostring(lsWidgets, -1),
LEN_ZONE_OPTION_STRING);
// TRACE("default string = %s", lua_tostring(lsWidgets, -1));
} else {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.unsignedValue = lua_tounsigned(lsWidgets, -1);
}
break;
case 3:
if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch) {
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch || option->type == ZoneOption::Slider) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->min.signedValue = lua_tointeger(lsWidgets, -1);
} else if (option->type == ZoneOption::Choice) {
luaL_checktype(lsWidgets, -1, LUA_TTABLE); // value is a table
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2); lua_pop(lsWidgets, 1)) {
option->choiceValues.push_back(lua_tostring(lsWidgets, -1));
}
}
break;
case 4:
if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch) {
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch || option->type == ZoneOption::Slider) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->max.signedValue = lua_tointeger(lsWidgets, -1);
}