feat(color): telemetry queues for Lua, enhance default widget options (#5926)
This commit is contained in:
@@ -36,7 +36,6 @@
|
||||
#define BITMAP_METATABLE "BITMAP*"
|
||||
|
||||
BitmapBuffer* luaLcdBuffer = nullptr;
|
||||
LuaWidget *runningFS = nullptr;
|
||||
|
||||
/*luadoc
|
||||
@function lcd.refresh()
|
||||
@@ -1386,8 +1385,8 @@ Exit full screen widget mode.
|
||||
*/
|
||||
static int luaLcdExitFullScreen(lua_State *L)
|
||||
{
|
||||
if (runningFS)
|
||||
runningFS->closeFullscreen();
|
||||
if (luaScriptManager)
|
||||
luaScriptManager->exitFullscreen();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,14 +28,11 @@
|
||||
|
||||
#include "api_colorlcd.h"
|
||||
|
||||
LuaLvglManager *luaLvglManager = nullptr;
|
||||
|
||||
static int luaLvglObj(lua_State *L, std::function<LvglWidgetObject*()> create, bool fullscreenOnly = false)
|
||||
{
|
||||
if (luaLvglManager && (!fullscreenOnly || luaLvglManager->isFullscreen())) {
|
||||
if (luaScriptManager && (!fullscreenOnly || luaScriptManager->isFullscreen())) {
|
||||
auto obj = create();
|
||||
obj->getParams(L, 1);
|
||||
obj->build(L);
|
||||
obj->create(L, 1);
|
||||
obj->push(L);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
@@ -46,24 +43,23 @@ static int luaLvglObj(lua_State *L, std::function<LvglWidgetObject*()> create, b
|
||||
|
||||
static int luaLvglObjEx(lua_State *L, std::function<LvglWidgetObjectBase*()> create, bool fullscreenOnly = false)
|
||||
{
|
||||
if (luaLvglManager && (!fullscreenOnly || luaLvglManager->isFullscreen())) {
|
||||
if (luaScriptManager && (!fullscreenOnly || luaScriptManager->isFullscreen())) {
|
||||
LvglWidgetObjectBase* p = nullptr;
|
||||
LvglWidgetObjectBase* prevParent = nullptr;
|
||||
if (lua_gettop(L) == 2) {
|
||||
p = LvglWidgetObjectBase::checkLvgl(L, 1);
|
||||
if (p) {
|
||||
prevParent = luaLvglManager->getTempParent();
|
||||
luaLvglManager->setTempParent(p);
|
||||
prevParent = luaScriptManager->getTempParent();
|
||||
luaScriptManager->setTempParent(p);
|
||||
}
|
||||
}
|
||||
|
||||
auto obj = create();
|
||||
obj->getParams(L, -1);
|
||||
obj->build(L);
|
||||
obj->create(L, -1);
|
||||
obj->push(L);
|
||||
|
||||
if (p)
|
||||
luaLvglManager->setTempParent((prevParent));
|
||||
luaScriptManager->setTempParent((prevParent));
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
@@ -74,8 +70,7 @@ static int luaLvglObjEx(lua_State *L, std::function<LvglWidgetObjectBase*()> cre
|
||||
static int luaLvglPopup(lua_State *L, std::function<LvglWidgetObjectBase*()> create)
|
||||
{
|
||||
auto obj = create();
|
||||
obj->getParams(L, 1);
|
||||
obj->build(L);
|
||||
obj->create(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -100,14 +95,14 @@ static int luaLvglSet(lua_State *L)
|
||||
|
||||
static int luaLvglClear(lua_State *L)
|
||||
{
|
||||
if (luaLvglManager) {
|
||||
if (luaScriptManager) {
|
||||
if (lua_gettop(L) == 1) {
|
||||
auto p = LvglWidgetObjectBase::checkLvgl(L, 1);
|
||||
if (p) {
|
||||
p->clear();
|
||||
}
|
||||
} else {
|
||||
luaLvglManager->clear();
|
||||
luaScriptManager->clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +145,15 @@ static int luaLvglDisable(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int luaLvglClose(lua_State *L)
|
||||
{
|
||||
auto p = LvglWidgetObjectBase::checkLvgl(L, 1);
|
||||
if (p) {
|
||||
p->close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class LvglWidgetParams
|
||||
{
|
||||
public:
|
||||
@@ -177,6 +181,7 @@ static void buildLvgl(lua_State *L, int srcIndex, int refIndex)
|
||||
{
|
||||
luaL_checktype(L, srcIndex, LUA_TTABLE);
|
||||
for (lua_pushnil(L); lua_next(L, srcIndex - 1); lua_pop(L, 1)) {
|
||||
auto t = lua_gettop(L);
|
||||
LvglWidgetParams p(L, -1);
|
||||
LvglWidgetObjectBase *obj = nullptr;
|
||||
if (strcasecmp(p.type, "label") == 0)
|
||||
@@ -201,7 +206,7 @@ static void buildLvgl(lua_State *L, int srcIndex, int refIndex)
|
||||
obj = new LvglWidgetQRCode();
|
||||
else if (strcasecmp(p.type, "box") == 0)
|
||||
obj = new LvglWidgetBox();
|
||||
else if (luaLvglManager->isFullscreen()) {
|
||||
else if (luaScriptManager->isFullscreen()) {
|
||||
if (strcasecmp(p.type, "button") == 0)
|
||||
obj = new LvglWidgetTextButton();
|
||||
if (strcasecmp(p.type, "momentaryButton") == 0)
|
||||
@@ -236,8 +241,7 @@ static void buildLvgl(lua_State *L, int srcIndex, int refIndex)
|
||||
obj = new LvglWidgetSetting();
|
||||
}
|
||||
if (obj) {
|
||||
obj->getParams(L, -1);
|
||||
obj->build(L);
|
||||
obj->create(L, -1);
|
||||
auto ref = obj->getRef(L);
|
||||
if (p.name) {
|
||||
lua_pushstring(L, p.name);
|
||||
@@ -246,26 +250,27 @@ static void buildLvgl(lua_State *L, int srcIndex, int refIndex)
|
||||
}
|
||||
if (p.hasChildren && obj->getWindow()) {
|
||||
lua_getfield(L, -1, "children");
|
||||
auto prevParent = luaLvglManager->getTempParent();
|
||||
luaLvglManager->setTempParent(obj);
|
||||
auto prevParent = luaScriptManager->getTempParent();
|
||||
luaScriptManager->setTempParent(obj);
|
||||
buildLvgl(L, -1, refIndex - 3);
|
||||
lua_pop(L, 1);
|
||||
luaLvglManager->setTempParent(prevParent);
|
||||
luaScriptManager->setTempParent(prevParent);
|
||||
}
|
||||
}
|
||||
lua_settop(L, t); // In case of errors in build functions
|
||||
}
|
||||
}
|
||||
|
||||
static int luaLvglBuild(lua_State *L)
|
||||
{
|
||||
if (luaLvglManager) {
|
||||
if (luaScriptManager) {
|
||||
LvglWidgetObjectBase* p = nullptr;
|
||||
LvglWidgetObjectBase* prevParent = nullptr;
|
||||
if (lua_gettop(L) == 2) {
|
||||
p = LvglWidgetObjectBase::checkLvgl(L, 1);
|
||||
if (p) {
|
||||
prevParent = luaLvglManager->getTempParent();
|
||||
luaLvglManager->setTempParent(p);
|
||||
prevParent = luaScriptManager->getTempParent();
|
||||
luaScriptManager->setTempParent(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +279,7 @@ static int luaLvglBuild(lua_State *L)
|
||||
buildLvgl(L, -2, -1);
|
||||
|
||||
if (p)
|
||||
luaLvglManager->setTempParent((prevParent));
|
||||
luaScriptManager->setTempParent((prevParent));
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
@@ -283,8 +288,8 @@ static int luaLvglBuild(lua_State *L)
|
||||
|
||||
static int luaLvglIsAppMode(lua_State *L)
|
||||
{
|
||||
if (luaLvglManager) {
|
||||
lua_pushboolean(L, luaLvglManager->isAppMode());
|
||||
if (luaScriptManager) {
|
||||
lua_pushboolean(L, luaScriptManager->isAppMode());
|
||||
} else {
|
||||
lua_pushboolean(L, false);
|
||||
}
|
||||
@@ -293,8 +298,8 @@ static int luaLvglIsAppMode(lua_State *L)
|
||||
|
||||
static int luaLvglIsFullscreen(lua_State *L)
|
||||
{
|
||||
if (luaLvglManager) {
|
||||
lua_pushboolean(L, luaLvglManager->isFullscreen());
|
||||
if (luaScriptManager) {
|
||||
lua_pushboolean(L, luaScriptManager->isFullscreen());
|
||||
} else {
|
||||
lua_pushboolean(L, false);
|
||||
}
|
||||
@@ -303,16 +308,16 @@ static int luaLvglIsFullscreen(lua_State *L)
|
||||
|
||||
static int luaLvglExitFullscreen(lua_State *L)
|
||||
{
|
||||
if (luaLvglManager)
|
||||
luaLvglManager->exitFullscreen();
|
||||
if (luaScriptManager)
|
||||
luaScriptManager->exitFullscreen();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int luaLvglGetContext(lua_State *L)
|
||||
{
|
||||
if (luaLvglManager && luaLvglManager->getContext() != LUA_REFNIL) {
|
||||
if (luaScriptManager && luaScriptManager->getContext() != LUA_REFNIL) {
|
||||
// Push context tanle onto Lua stack (return object)
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, luaLvglManager->getContext());
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, luaScriptManager->getContext());
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
@@ -354,8 +359,8 @@ LROT_BEGIN(lvgllib, NULL, 0)
|
||||
LROT_FUNCENTRY(switch, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetSwitchPicker(); }, true); })
|
||||
LROT_FUNCENTRY(source, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetSourcePicker(); }, true); })
|
||||
// Containers
|
||||
LROT_FUNCENTRY(box, [](lua_State* L) { return luaLvglObj(L, []() { return new LvglWidgetBox(); }, true); })
|
||||
LROT_FUNCENTRY(setting, [](lua_State* L) { return luaLvglObj(L, []() { return new LvglWidgetSetting(); }, true); })
|
||||
LROT_FUNCENTRY(box, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetBox(); }); })
|
||||
LROT_FUNCENTRY(setting, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetSetting(); }, true); })
|
||||
LROT_FUNCENTRY(page, [](lua_State* L) { return luaLvglObj(L, []() { return new LvglWidgetPage(); }, true); })
|
||||
LROT_FUNCENTRY(dialog, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetDialog(); }, true); })
|
||||
// Dialogs
|
||||
@@ -367,6 +372,7 @@ LROT_BEGIN(lvgllib, NULL, 0)
|
||||
LROT_FUNCENTRY(hide, luaLvglHide)
|
||||
LROT_FUNCENTRY(enable, luaLvglEnable)
|
||||
LROT_FUNCENTRY(disable, luaLvglDisable)
|
||||
LROT_FUNCENTRY(close, luaLvglClose)
|
||||
LROT_NUMENTRY(FLOW_ROW, LV_FLEX_FLOW_ROW)
|
||||
LROT_NUMENTRY(FLOW_COLUMN, LV_FLEX_FLOW_COLUMN)
|
||||
LROT_NUMENTRY(PAD_TINY, PAD_TINY)
|
||||
@@ -440,12 +446,16 @@ LROT_BEGIN(lvgl_mt, NULL, LROT_MASK_GC_INDEX)
|
||||
LROT_FUNCENTRY(timer, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetTimerPicker(); }, true); })
|
||||
LROT_FUNCENTRY(switch, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetSwitchPicker(); }, true); })
|
||||
LROT_FUNCENTRY(source, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetSourcePicker(); }, true); })
|
||||
// Containers
|
||||
LROT_FUNCENTRY(box, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetBox(); }); })
|
||||
LROT_FUNCENTRY(setting, [](lua_State* L) { return luaLvglObjEx(L, []() { return new LvglWidgetSetting(); }, true); })
|
||||
// Object manipulation functions
|
||||
LROT_FUNCENTRY(set, luaLvglSet)
|
||||
LROT_FUNCENTRY(show, luaLvglShow)
|
||||
LROT_FUNCENTRY(hide, luaLvglHide)
|
||||
LROT_FUNCENTRY(enable, luaLvglEnable)
|
||||
LROT_FUNCENTRY(disable, luaLvglDisable)
|
||||
LROT_FUNCENTRY(close, luaLvglClose)
|
||||
LROT_END(lvgl_mt, NULL, LROT_MASK_GC_INDEX)
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -898,6 +898,24 @@ static int luaGetRotEncMode(lua_State * L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static TelemetryQueue* getTelemetryQueue()
|
||||
{
|
||||
#if defined(COLORLCD)
|
||||
if (luaScriptManager) {
|
||||
luaScriptManager->createTelemetryQueue();
|
||||
return luaScriptManager->telemetryQueue();
|
||||
} else {
|
||||
if (!luaInputTelemetryFifo)
|
||||
luaInputTelemetryFifo = new TelemetryQueue();
|
||||
return luaInputTelemetryFifo;
|
||||
}
|
||||
#else
|
||||
if (!luaInputTelemetryFifo)
|
||||
luaInputTelemetryFifo = new TelemetryQueue();
|
||||
return luaInputTelemetryFifo;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function sportTelemetryPop()
|
||||
|
||||
@@ -917,23 +935,20 @@ the LUA telemetry receive queue.
|
||||
*/
|
||||
static int luaSportTelemetryPop(lua_State * L)
|
||||
{
|
||||
if (!luaInputTelemetryFifo) {
|
||||
luaInputTelemetryFifo = new Fifo<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE>();
|
||||
if (!luaInputTelemetryFifo) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
auto queue = getTelemetryQueue();
|
||||
|
||||
if (luaInputTelemetryFifo->size() >= sizeof(SportTelemetryPacket)) {
|
||||
SportTelemetryPacket packet;
|
||||
for (uint8_t i=0; i<sizeof(packet); i++) {
|
||||
luaInputTelemetryFifo->pop(packet.raw[i]);
|
||||
if (queue) {
|
||||
if (queue->size() >= sizeof(SportTelemetryPacket)) {
|
||||
SportTelemetryPacket packet;
|
||||
for (uint8_t i=0; i<sizeof(packet); i++) {
|
||||
queue->pop(packet.raw[i]);
|
||||
}
|
||||
lua_pushinteger(L, packet.physicalId);
|
||||
lua_pushinteger(L, packet.primId);
|
||||
lua_pushinteger(L, packet.dataId);
|
||||
lua_pushinteger(L, packet.value);
|
||||
return 4;
|
||||
}
|
||||
lua_pushinteger(L, packet.physicalId);
|
||||
lua_pushinteger(L, packet.primId);
|
||||
lua_pushinteger(L, packet.dataId);
|
||||
lua_pushinteger(L, packet.value);
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1144,27 +1159,24 @@ Pops a received Crossfire Telemetry packet from the queue.
|
||||
*/
|
||||
static int luaCrossfireTelemetryPop(lua_State * L)
|
||||
{
|
||||
if (!luaInputTelemetryFifo) {
|
||||
luaInputTelemetryFifo = new Fifo<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE>();
|
||||
if (!luaInputTelemetryFifo) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
auto queue = getTelemetryQueue();
|
||||
|
||||
uint8_t length = 0, data = 0;
|
||||
if (luaInputTelemetryFifo->probe(length) && luaInputTelemetryFifo->size() >= uint32_t(length)) {
|
||||
// length value includes the length field
|
||||
luaInputTelemetryFifo->pop(length);
|
||||
luaInputTelemetryFifo->pop(data); // command
|
||||
lua_pushinteger(L, data);
|
||||
lua_newtable(L);
|
||||
for (uint8_t i=1; i<length-1; i++) {
|
||||
luaInputTelemetryFifo->pop(data);
|
||||
lua_pushinteger(L, i);
|
||||
if (queue) {
|
||||
uint8_t length = 0, data = 0;
|
||||
if (queue->probe(length) && queue->size() >= uint32_t(length)) {
|
||||
// length value includes the length field
|
||||
queue->pop(length);
|
||||
queue->pop(data); // command
|
||||
lua_pushinteger(L, data);
|
||||
lua_settable(L, -3);
|
||||
lua_newtable(L);
|
||||
for (uint8_t i=1; i<length-1; i++) {
|
||||
queue->pop(data);
|
||||
lua_pushinteger(L, i);
|
||||
lua_pushinteger(L, data);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1268,27 +1280,24 @@ Pops a received Ghost Telemetry packet from the queue.
|
||||
*/
|
||||
static int luaGhostTelemetryPop(lua_State * L)
|
||||
{
|
||||
if (!luaInputTelemetryFifo) {
|
||||
luaInputTelemetryFifo = new Fifo<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE>();
|
||||
if (!luaInputTelemetryFifo) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
auto queue = getTelemetryQueue();
|
||||
|
||||
uint8_t length = 0, data = 0;
|
||||
if (luaInputTelemetryFifo->probe(length) && luaInputTelemetryFifo->size() >= uint32_t(length)) {
|
||||
// length value includes type(1B), payload, crc(1B)
|
||||
luaInputTelemetryFifo->pop(length);
|
||||
luaInputTelemetryFifo->pop(data); // type
|
||||
lua_pushinteger(L, data); // return type
|
||||
lua_newtable(L);
|
||||
for (uint8_t i=0; i<length-2; i++) {
|
||||
luaInputTelemetryFifo->pop(data);
|
||||
lua_pushinteger(L, i + 1);
|
||||
lua_pushinteger(L, data);
|
||||
lua_settable(L, -3);
|
||||
if (queue) {
|
||||
uint8_t length = 0, data = 0;
|
||||
if (queue->probe(length) && queue->size() >= uint32_t(length)) {
|
||||
// length value includes type(1B), payload, crc(1B)
|
||||
queue->pop(length);
|
||||
queue->pop(data); // type
|
||||
lua_pushinteger(L, data); // return type
|
||||
lua_newtable(L);
|
||||
for (uint8_t i=0; i<length-2; i++) {
|
||||
queue->pop(data);
|
||||
lua_pushinteger(L, i + 1);
|
||||
lua_pushinteger(L, data);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2193,8 +2202,8 @@ Get percent of already used Lua instructions in current script execution cycle.
|
||||
static int luaGetUsage(lua_State * L)
|
||||
{
|
||||
#if defined(COLORLCD)
|
||||
if (luaLvglManager && luaLvglManager->useLvglLayout()) {
|
||||
lua_pushinteger(L, luaLvglManager->refreshInstructionsPercent);
|
||||
if (luaScriptManager && luaScriptManager->useLvglLayout()) {
|
||||
lua_pushinteger(L, luaScriptManager->refreshInstructionsPercent);
|
||||
} else {
|
||||
lua_pushinteger(L, instructionsPercent);
|
||||
}
|
||||
@@ -2592,30 +2601,10 @@ to the fields in the table returned by `model.getLogicalSwitch(switch)` identify
|
||||
static int luaGetSwitchIndex(lua_State * L)
|
||||
{
|
||||
const char * name = luaL_checkstring(L, 1);
|
||||
bool negate = false;
|
||||
bool found = false;
|
||||
swsrc_t idx;
|
||||
swsrc_t idx = getSwitchIndex(name, true);
|
||||
|
||||
if (name[0] == '!') {
|
||||
name++;
|
||||
negate = true;
|
||||
}
|
||||
|
||||
for (idx = SWSRC_NONE; idx < SWSRC_COUNT; idx++) {
|
||||
if (isSwitchAvailable(idx, ModelCustomFunctionsContext)) {
|
||||
char* s = getSwitchPositionName(idx);
|
||||
if (!strncasecmp(s, name, 31)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (negate)
|
||||
idx = -idx;
|
||||
if (idx != SWSRC_INVERT)
|
||||
lua_pushinteger(L, idx);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
@@ -2715,8 +2704,7 @@ static int luaSwitches(lua_State * L)
|
||||
} else
|
||||
last = SWSRC_LAST;
|
||||
|
||||
lua_pushcfunction(L, luaNextSwitch);
|
||||
lua_pushinteger(L, last);
|
||||
lua_pushcfunction(L, luaNextSwitch); lua_pushinteger(L, last);
|
||||
lua_pushinteger(L, first);
|
||||
return 3;
|
||||
}
|
||||
@@ -2737,21 +2725,9 @@ This function is rather time consuming, and should not be used repeatedly in a s
|
||||
static int luaGetSourceIndex(lua_State* const L)
|
||||
{
|
||||
const char* const name = luaL_checkstring(L, 1);
|
||||
bool found = false;
|
||||
mixsrc_t idx;
|
||||
mixsrc_t idx = getSourceIndex(name, true);
|
||||
|
||||
for (idx = MIXSRC_NONE; idx <= MIXSRC_LAST_TELEM; idx++) {
|
||||
if (isSourceAvailable(idx)) {
|
||||
char srcName[maxSourceNameLength];
|
||||
getSourceString(srcName, idx);
|
||||
if (!strncasecmp(srcName, name)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
if (idx >= 0)
|
||||
lua_pushinteger(L, idx);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
@@ -61,12 +61,6 @@ extern bool luaLcdAllowed;
|
||||
class BitmapBuffer;
|
||||
extern BitmapBuffer* luaLcdBuffer;
|
||||
|
||||
class LuaWidget;
|
||||
extern LuaWidget* runningFS;
|
||||
|
||||
class LuaLvglManager;
|
||||
extern LuaLvglManager* luaLvglManager;
|
||||
|
||||
extern uint32_t luaExtraMemoryUsage;
|
||||
void luaInitThemesAndWidgets();
|
||||
#endif
|
||||
|
||||
+306
-203
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,30 @@
|
||||
#define LVGL_METATABLE "LVGL*"
|
||||
#define LVGL_SIMPLEMETATABLE "LVGLSIMPLE*"
|
||||
|
||||
class LuaScriptManager;
|
||||
class LvglDialog;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct LvglParamFuncOrValue
|
||||
{
|
||||
public:
|
||||
enum ParamType {
|
||||
PVALUE,
|
||||
PTXT,
|
||||
};
|
||||
|
||||
int function;
|
||||
union {
|
||||
LcdFlags flags;
|
||||
coord_t coord;
|
||||
const char* txt;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
void parse(lua_State *L, ParamType typ = PVALUE);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class LvglWidgetObjectBase
|
||||
@@ -36,9 +60,6 @@ class LvglWidgetObjectBase
|
||||
void push(lua_State *L);
|
||||
void saveLvglObjectRef(int ref);
|
||||
|
||||
void getParams(lua_State *L, int index);
|
||||
|
||||
virtual void build(lua_State *L);
|
||||
virtual bool callRefs(lua_State *L);
|
||||
virtual void clearRefs(lua_State *L);
|
||||
void clearChildRefs(lua_State *L);
|
||||
@@ -47,12 +68,14 @@ class LvglWidgetObjectBase
|
||||
virtual void hide() = 0;
|
||||
virtual void enable() {};
|
||||
virtual void disable() {};
|
||||
virtual void close() {};
|
||||
|
||||
virtual void setColor(LcdFlags newColor) {}
|
||||
virtual void setOpacity(uint8_t newOpa) {}
|
||||
virtual void setPos(coord_t x, coord_t y) {}
|
||||
virtual void setSize(coord_t w, coord_t h) {}
|
||||
|
||||
void create(lua_State *L, int index);
|
||||
void update(lua_State *L);
|
||||
|
||||
virtual Window *getWindow() const = 0;
|
||||
@@ -66,21 +89,22 @@ class LvglWidgetObjectBase
|
||||
std::vector<int> lvglObjectRefs;
|
||||
const char* metatable = nullptr;
|
||||
bool clearRequest = false;
|
||||
LuaLvglManager *lvglManager = nullptr;
|
||||
LuaScriptManager *lvglManager = nullptr;
|
||||
coord_t x = 0, y = 0, w = LV_SIZE_CONTENT, h = LV_SIZE_CONTENT;
|
||||
LcdFlags color = COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX);
|
||||
LcdFlags currentColor = -1;
|
||||
uint8_t opacity = LV_OPA_COVER;
|
||||
int getColorFunction = LUA_REFNIL;
|
||||
int getOpacityFunction = LUA_REFNIL;
|
||||
int getVisibleFunction = LUA_REFNIL;
|
||||
int getSizeFunction = LUA_REFNIL;
|
||||
int getPosFunction = LUA_REFNIL;
|
||||
LvglParamFuncOrValue color = { .function = LUA_REFNIL, .flags = COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)};
|
||||
LvglParamFuncOrValue opacity = { .function = LUA_REFNIL, .value = LV_OPA_COVER};
|
||||
|
||||
virtual void build(lua_State *L);
|
||||
virtual void refresh();
|
||||
|
||||
virtual void parseParam(lua_State *L, const char *key);
|
||||
|
||||
void getParams(lua_State *L, int index);
|
||||
|
||||
bool colorChanged(LcdFlags newColor);
|
||||
|
||||
void clearRef(lua_State *L, int& ref);
|
||||
@@ -128,26 +152,23 @@ class LvglWidgetLabel : public LvglSimpleWidgetObject
|
||||
void setFont(LcdFlags font);
|
||||
void setAlign(LcdFlags align);
|
||||
|
||||
void build(lua_State *L) override;
|
||||
bool callRefs(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
uint32_t textHash = -1;
|
||||
|
||||
const char *txt = "";
|
||||
LcdFlags font = FONT(STD);
|
||||
LcdFlags align = LEFT;
|
||||
int getTextFunction = LUA_REFNIL;
|
||||
int getFontFunction = LUA_REFNIL;
|
||||
int getAlignFunction = LUA_REFNIL;
|
||||
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;
|
||||
void refresh() override
|
||||
{
|
||||
setText(txt);
|
||||
setFont(font);
|
||||
setAlign(align);
|
||||
setText(txt.txt);
|
||||
setFont(font.flags);
|
||||
setAlign(align.flags);
|
||||
LvglSimpleWidgetObject::refresh();
|
||||
}
|
||||
};
|
||||
@@ -164,8 +185,6 @@ class LvglWidgetLineBase : public LvglSimpleWidgetObject
|
||||
void setPos(coord_t x, coord_t y) override;
|
||||
void setSize(coord_t w, coord_t h) override;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
bool rounded = false;
|
||||
int dashGap = 0;
|
||||
@@ -174,6 +193,7 @@ class LvglWidgetLineBase : public LvglSimpleWidgetObject
|
||||
|
||||
virtual void setLine() = 0;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
void refresh() override;
|
||||
};
|
||||
@@ -205,24 +225,30 @@ class LvglWidgetVLine : public LvglWidgetLineBase
|
||||
class LvglWidgetLine : public LvglSimpleWidgetObject
|
||||
{
|
||||
public:
|
||||
LvglWidgetLine() : LvglSimpleWidgetObject() {}
|
||||
LvglWidgetLine();
|
||||
~LvglWidgetLine();
|
||||
|
||||
void setColor(LcdFlags newColor) override;
|
||||
void setOpacity(uint8_t newOpa) override;
|
||||
void setPos(coord_t x, coord_t y) override;
|
||||
void setSize(coord_t w, coord_t h) override;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
bool callRefs(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
coord_t thickness = 1;
|
||||
bool rounded = false;
|
||||
size_t ptCnt = 0;
|
||||
lv_point_t* pts = nullptr;
|
||||
uint32_t ptsHash = -1;
|
||||
lv_obj_t* parent = nullptr;
|
||||
int getPointsFunction = LUA_REFNIL;
|
||||
|
||||
void setLine();
|
||||
|
||||
void getPt(lua_State* L, int n);
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
void refresh() override;
|
||||
};
|
||||
@@ -232,22 +258,27 @@ class LvglWidgetLine : public LvglSimpleWidgetObject
|
||||
class LvglWidgetTriangle : public LvglSimpleWidgetObject
|
||||
{
|
||||
public:
|
||||
LvglWidgetTriangle() : LvglSimpleWidgetObject() {}
|
||||
LvglWidgetTriangle();
|
||||
~LvglWidgetTriangle();
|
||||
|
||||
void setColor(LcdFlags newColor) override;
|
||||
void setSize(coord_t w, coord_t h) override;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
bool callRefs(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
coord_t px[3] = {0}, py[3] = {0};
|
||||
lv_point_t pts[3] = {0};
|
||||
uint32_t ptsHash = -1;
|
||||
MaskBitmap* mask = nullptr;
|
||||
lv_obj_t* parent = nullptr;
|
||||
int getPointsFunction = LUA_REFNIL;
|
||||
|
||||
void fillTriangle();
|
||||
void fillLine(coord_t x1, coord_t x2, coord_t y);
|
||||
|
||||
void getPt(lua_State* L, int n);
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
void refresh() override;
|
||||
};
|
||||
@@ -290,9 +321,8 @@ class LvglWidgetBox : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetBox() : LvglWidgetObject() {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
void build(lua_State *L) override;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -302,11 +332,10 @@ class LvglWidgetSetting : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetSetting() : LvglWidgetObject() {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
const char *txt = "";
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -320,12 +349,11 @@ class LvglWidgetBorderedObject : public LvglWidgetObject
|
||||
void setColor(LcdFlags newColor) override;
|
||||
void setOpacity(uint8_t newOpa) override;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
coord_t thickness = 1;
|
||||
bool filled = false;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -343,14 +371,12 @@ class LvglWidgetRoundObject : public LvglWidgetBorderedObject
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
coord_t radius = 0;
|
||||
|
||||
int getRadiusFunction = LUA_REFNIL;
|
||||
LvglParamFuncOrValue radius = { .function = LUA_REFNIL, .coord = 0};
|
||||
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
void refresh() override
|
||||
{
|
||||
setRadius(radius);
|
||||
setRadius(radius.coord);
|
||||
LvglWidgetObject::refresh();
|
||||
}
|
||||
};
|
||||
@@ -362,11 +388,10 @@ class LvglWidgetRectangle : public LvglWidgetBorderedObject
|
||||
public:
|
||||
LvglWidgetRectangle() : LvglWidgetBorderedObject() {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
coord_t rounded = 0;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -377,9 +402,8 @@ class LvglWidgetCircle : public LvglWidgetRoundObject
|
||||
public:
|
||||
LvglWidgetCircle() : LvglWidgetRoundObject() {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
void build(lua_State *L) override;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -394,21 +418,19 @@ class LvglWidgetArc : public LvglWidgetRoundObject
|
||||
void setStartAngle(coord_t angle);
|
||||
void setEndAngle(coord_t angle);
|
||||
|
||||
void build(lua_State *L) override;
|
||||
bool callRefs(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
coord_t startAngle = 0, endAngle = 0;
|
||||
|
||||
int getStartAngleFunction = LUA_REFNIL;
|
||||
int getEndAngleFunction = LUA_REFNIL;
|
||||
LvglParamFuncOrValue startAngle = { .function = LUA_REFNIL, .coord = 0};
|
||||
LvglParamFuncOrValue endAngle = { .function = LUA_REFNIL, .coord = 0};
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
void refresh() override
|
||||
{
|
||||
setStartAngle(startAngle);
|
||||
setEndAngle(endAngle);
|
||||
setStartAngle(startAngle.coord);
|
||||
setEndAngle(endAngle.coord);
|
||||
LvglWidgetRoundObject::refresh();
|
||||
}
|
||||
};
|
||||
@@ -420,12 +442,11 @@ class LvglWidgetImage : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetImage() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
std::string filename;
|
||||
bool fillFrame = false;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -436,12 +457,11 @@ class LvglWidgetQRCode : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetQRCode() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
std::string data;
|
||||
LcdFlags bgColor = COLOR2FLAGS(COLOR_THEME_SECONDARY3_INDEX);
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -452,7 +472,7 @@ class LvglWidgetTextButtonBase : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetTextButtonBase() : LvglWidgetObject(LVGL_SIMPLEMETATABLE)
|
||||
{
|
||||
color = -1; // ignore unless overridden
|
||||
color.flags = -1; // ignore unless overridden
|
||||
}
|
||||
|
||||
void setText(const char *s);
|
||||
@@ -485,13 +505,13 @@ class LvglWidgetTextButton : public LvglWidgetTextButtonBase
|
||||
void setFont(LcdFlags font);
|
||||
void setChecked(bool check);
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
bool checked = false;
|
||||
int longPressFunction = LUA_REFNIL;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
void refresh() override
|
||||
{
|
||||
@@ -509,12 +529,12 @@ class LvglWidgetMomentaryButton : public LvglWidgetTextButtonBase
|
||||
|
||||
void setFont(LcdFlags font);
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
int releaseFunction = LUA_REFNIL;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -525,13 +545,13 @@ class LvglWidgetToggleSwitch : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetToggleSwitch() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -542,7 +562,6 @@ class LvglWidgetTextEdit : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetTextEdit() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
@@ -552,6 +571,7 @@ class LvglWidgetTextEdit : public LvglWidgetObject
|
||||
|
||||
int setFunction = LUA_REFNIL;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -562,7 +582,6 @@ class LvglWidgetNumberEdit : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetNumberEdit() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
@@ -572,6 +591,7 @@ class LvglWidgetNumberEdit : public LvglWidgetObject
|
||||
int setFunction = LUA_REFNIL;
|
||||
int dispFunction = LUA_REFNIL;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -582,7 +602,7 @@ class LvglWidgetSliderBase : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetSliderBase() : LvglWidgetObject(LVGL_SIMPLEMETATABLE)
|
||||
{
|
||||
color = -1;
|
||||
color.flags = -1;
|
||||
}
|
||||
|
||||
void setColor(LcdFlags newColor) override;
|
||||
@@ -605,6 +625,7 @@ class LvglWidgetSlider : public LvglWidgetSliderBase
|
||||
public:
|
||||
LvglWidgetSlider() : LvglWidgetSliderBase() {}
|
||||
|
||||
protected:
|
||||
void build(lua_State *L) override;
|
||||
};
|
||||
|
||||
@@ -615,6 +636,7 @@ class LvglWidgetVerticalSlider : public LvglWidgetSliderBase
|
||||
public:
|
||||
LvglWidgetVerticalSlider() : LvglWidgetSliderBase() {}
|
||||
|
||||
protected:
|
||||
void build(lua_State *L) override;
|
||||
};
|
||||
|
||||
@@ -625,7 +647,6 @@ class LvglWidgetPage : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetPage() : LvglWidgetObject() {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
@@ -635,6 +656,7 @@ class LvglWidgetPage : public LvglWidgetObject
|
||||
|
||||
int backActionFunction = LUA_REFNIL;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -645,14 +667,16 @@ class LvglWidgetDialog : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetDialog() : LvglWidgetObject() {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
void close() override;
|
||||
|
||||
protected:
|
||||
const char *title = nullptr;
|
||||
LvglDialog* dialog = nullptr;
|
||||
|
||||
int closeFunction = LUA_REFNIL;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -663,7 +687,6 @@ class LvglWidgetConfirmDialog : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetConfirmDialog() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void clearRefs(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
@@ -673,6 +696,7 @@ class LvglWidgetConfirmDialog : public LvglWidgetObject
|
||||
int confirmFunction = LUA_REFNIL;
|
||||
int cancelFunction = LUA_REFNIL;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -683,13 +707,12 @@ class LvglWidgetMessageDialog : public LvglWidgetObject
|
||||
public:
|
||||
LvglWidgetMessageDialog() : LvglWidgetObject(LVGL_SIMPLEMETATABLE) {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
const char *title = nullptr;
|
||||
const char *message = nullptr;
|
||||
const char *details = nullptr;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -716,12 +739,11 @@ class LvglWidgetChoice : public LvglWidgetPicker
|
||||
public:
|
||||
LvglWidgetChoice() : LvglWidgetPicker() {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
std::string title;
|
||||
std::vector<std::string> values;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -732,6 +754,7 @@ class LvglWidgetFontPicker : public LvglWidgetPicker
|
||||
public:
|
||||
LvglWidgetFontPicker() : LvglWidgetPicker() {}
|
||||
|
||||
protected:
|
||||
void build(lua_State *L) override;
|
||||
};
|
||||
|
||||
@@ -742,6 +765,7 @@ class LvglWidgetAlignPicker : public LvglWidgetPicker
|
||||
public:
|
||||
LvglWidgetAlignPicker() : LvglWidgetPicker() {}
|
||||
|
||||
protected:
|
||||
void build(lua_State *L) override;
|
||||
};
|
||||
|
||||
@@ -752,6 +776,7 @@ class LvglWidgetColorPicker : public LvglWidgetPicker
|
||||
public:
|
||||
LvglWidgetColorPicker() : LvglWidgetPicker() {}
|
||||
|
||||
protected:
|
||||
void build(lua_State *L) override;
|
||||
};
|
||||
|
||||
@@ -762,6 +787,7 @@ class LvglWidgetTimerPicker : public LvglWidgetPicker
|
||||
public:
|
||||
LvglWidgetTimerPicker() : LvglWidgetPicker() {}
|
||||
|
||||
protected:
|
||||
void build(lua_State *L) override;
|
||||
};
|
||||
|
||||
@@ -772,11 +798,10 @@ class LvglWidgetSwitchPicker : public LvglWidgetPicker
|
||||
public:
|
||||
LvglWidgetSwitchPicker() : LvglWidgetPicker() {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
uint32_t filter = 0xFFFFFFFF;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
@@ -787,11 +812,10 @@ class LvglWidgetSourcePicker : public LvglWidgetPicker
|
||||
public:
|
||||
LvglWidgetSourcePicker() : LvglWidgetPicker() {}
|
||||
|
||||
void build(lua_State *L) override;
|
||||
|
||||
protected:
|
||||
uint32_t filter = 0xFFFFFFFF;
|
||||
|
||||
void build(lua_State *L) override;
|
||||
void parseParam(lua_State *L, const char *key) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
#define MAX_INSTRUCTIONS (20000 / 100)
|
||||
|
||||
LuaScriptManager *luaScriptManager = nullptr;
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
uint32_t LuaEventHandler::downTime = 0;
|
||||
uint32_t LuaEventHandler::tapTime = 0;
|
||||
@@ -140,7 +142,7 @@ void LuaEventHandler::event_cb(lv_event_t* e)
|
||||
#endif
|
||||
}
|
||||
|
||||
void LuaEventHandler::onClicked()
|
||||
void LuaEventHandler::onClickedEvent()
|
||||
{
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
auto click_source = lv_indev_get_act();
|
||||
@@ -167,7 +169,7 @@ void LuaEventHandler::onClicked()
|
||||
luaPushEvent(EVT_KEY_BREAK(KEY_ENTER));
|
||||
}
|
||||
|
||||
void LuaEventHandler::onCancel() {
|
||||
void LuaEventHandler::onCancelEvent() {
|
||||
luaPushEvent(EVT_KEY_BREAK(KEY_EXIT));
|
||||
}
|
||||
|
||||
@@ -217,18 +219,41 @@ void LuaWidget::redraw_cb(lv_event_t* e)
|
||||
buf.setClippingRect(clipping.x1 - a.x1, clipping.x2 + 1 - a.x1,
|
||||
clipping.y1 - a.y1, clipping.y2 + 1 - a.y1);
|
||||
|
||||
auto save = luaScriptManager;
|
||||
luaScriptManager = widget;
|
||||
widget->refresh(&buf);
|
||||
luaScriptManager = save;
|
||||
}
|
||||
}
|
||||
|
||||
LuaWidget::LuaWidget(const WidgetFactory* factory, Window* parent,
|
||||
const rect_t& rect, WidgetPersistentData* persistentData,
|
||||
int luaScriptContextRef, int zoneRectDataRef, int optionsDataRef) :
|
||||
int zoneRectDataRef, int optionsDataRef,
|
||||
int createFunctionRef, std::string path) :
|
||||
Widget(factory, parent, rect, persistentData),
|
||||
zoneRectDataRef(zoneRectDataRef), optionsDataRef(optionsDataRef),
|
||||
errorMessage(nullptr)
|
||||
{
|
||||
this->luaScriptContextRef = luaScriptContextRef;
|
||||
// Push create function
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, createFunctionRef);
|
||||
// Push stored zone for 'create' call
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, zoneRectDataRef);
|
||||
// Push stored options for 'create' call
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, optionsDataRef);
|
||||
// Push widget folder path
|
||||
lua_pushstring(lsWidgets, path.c_str());
|
||||
|
||||
auto save = luaScriptManager;
|
||||
luaScriptManager = this;
|
||||
|
||||
if (lua_pcall(lsWidgets, 3, 1, 0) == LUA_OK) {
|
||||
luaScriptContextRef = luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
|
||||
} else {
|
||||
luaScriptContextRef = LUA_NOREF;
|
||||
setErrorMessage("create()");
|
||||
}
|
||||
|
||||
luaScriptManager = save;
|
||||
|
||||
if (useLvglLayout()) {
|
||||
update();
|
||||
@@ -252,7 +277,7 @@ void LuaWidget::onClicked()
|
||||
return;
|
||||
}
|
||||
|
||||
LuaEventHandler::onClicked();
|
||||
LuaScriptManager::onClickedEvent();
|
||||
}
|
||||
|
||||
void LuaWidget::onCancel()
|
||||
@@ -262,7 +287,7 @@ void LuaWidget::onCancel()
|
||||
return;
|
||||
}
|
||||
|
||||
LuaEventHandler::onCancel();
|
||||
LuaScriptManager::onCancelEvent();
|
||||
}
|
||||
|
||||
void LuaWidget::checkEvents()
|
||||
@@ -286,8 +311,9 @@ void LuaWidget::checkEvents()
|
||||
lv_obj_get_coords(lvobj, &a);
|
||||
// Check widget is at least partially visible
|
||||
if (a.x2 >= 0 && a.x1 < LCD_W) {
|
||||
auto save = luaScriptManager;
|
||||
PROTECT_LUA() {
|
||||
luaLvglManager = this;
|
||||
luaScriptManager = this;
|
||||
refresh(nullptr);
|
||||
if (!errorMessage) {
|
||||
if (!callRefs(lsWidgets)) {
|
||||
@@ -298,7 +324,7 @@ void LuaWidget::checkEvents()
|
||||
} else {
|
||||
// TODO: error handling
|
||||
}
|
||||
luaLvglManager = nullptr;
|
||||
luaScriptManager = save;
|
||||
UNPROTECT_LUA();
|
||||
}
|
||||
}
|
||||
@@ -325,7 +351,7 @@ void LuaWidget::update()
|
||||
// Get options table and update values
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, optionsDataRef);
|
||||
int i = 0;
|
||||
for (const ZoneOption* option = getOptions(); option->name; option++, i++) {
|
||||
for (const ZoneOption* option = getOptionDefinitions(); option->name; option++, i++) {
|
||||
auto optVal = getOptionValue(i);
|
||||
switch (option->type) {
|
||||
case ZoneOption::String:
|
||||
@@ -347,7 +373,7 @@ void LuaWidget::update()
|
||||
lua_setfield(lsWidgets, -2, option->name);
|
||||
}
|
||||
|
||||
if (useLvglLayout()) luaLvglManager = this;
|
||||
luaScriptManager = this;
|
||||
|
||||
if (lua_pcall(lsWidgets, 2, 0, 0) != 0)
|
||||
setErrorMessage("update()");
|
||||
@@ -370,7 +396,7 @@ void LuaWidget::update()
|
||||
}
|
||||
}
|
||||
|
||||
luaLvglManager = nullptr;
|
||||
luaScriptManager = nullptr;
|
||||
}
|
||||
|
||||
// Update table on top of Lua stack - set entry with name 'idx' to value 'val'
|
||||
@@ -499,12 +525,10 @@ void LuaWidget::refresh(BitmapBuffer* dc)
|
||||
// scripts
|
||||
bool lla = luaLcdAllowed;
|
||||
luaLcdAllowed = true;
|
||||
runningFS = this;
|
||||
|
||||
if (lua_pcall(lsWidgets, 3, 0, 0) != 0) {
|
||||
setErrorMessage("refresh()");
|
||||
}
|
||||
runningFS = nullptr;
|
||||
// Remove LCD
|
||||
luaLcdAllowed = lla;
|
||||
luaLcdBuffer = nullptr;
|
||||
@@ -521,18 +545,19 @@ void LuaWidget::background()
|
||||
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaFactory()->backgroundFunction);
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaScriptContextRef);
|
||||
runningFS = this;
|
||||
auto save = luaScriptManager;
|
||||
luaScriptManager = this;
|
||||
if (lua_pcall(lsWidgets, 1, 0, 0) != 0) {
|
||||
setErrorMessage("background()");
|
||||
}
|
||||
runningFS = nullptr;
|
||||
luaScriptManager = save;
|
||||
}
|
||||
}
|
||||
|
||||
void LuaWidget::onEvent(event_t event)
|
||||
{
|
||||
if (fullscreen) {
|
||||
LuaEventHandler::onLuaEvent(event);
|
||||
LuaScriptManager::onLuaEvent(event);
|
||||
}
|
||||
Widget::onEvent(event);
|
||||
}
|
||||
@@ -547,10 +572,10 @@ bool LuaWidget::useLvglLayout() const { return luaFactory()->useLvglLayout(); }
|
||||
|
||||
bool LuaWidget::isAppMode() const
|
||||
{
|
||||
return fullscreen && ViewMain::instance()->isAppMode();
|
||||
return ((WidgetsContainer*)parent)->isAppMode();
|
||||
}
|
||||
|
||||
void LuaLvglManager::saveLvglObjectRef(int ref)
|
||||
void LuaScriptManager::saveLvglObjectRef(int ref)
|
||||
{
|
||||
if (tempParent)
|
||||
tempParent->saveLvglObjectRef(ref);
|
||||
@@ -558,7 +583,7 @@ void LuaLvglManager::saveLvglObjectRef(int ref)
|
||||
lvglObjectRefs.push_back(ref);
|
||||
}
|
||||
|
||||
void LuaLvglManager::clearRefs(lua_State *L)
|
||||
void LuaScriptManager::clearRefs(lua_State *L)
|
||||
{
|
||||
for (size_t i = 0; i < lvglObjectRefs.size(); i += 1) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lvglObjectRefs[i]);
|
||||
@@ -569,7 +594,7 @@ void LuaLvglManager::clearRefs(lua_State *L)
|
||||
lvglObjectRefs.clear();
|
||||
}
|
||||
|
||||
bool LuaLvglManager::callRefs(lua_State *L)
|
||||
bool LuaScriptManager::callRefs(lua_State *L)
|
||||
{
|
||||
for (size_t i = 0; i < lvglObjectRefs.size(); i += 1) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lvglObjectRefs[i]);
|
||||
@@ -579,3 +604,20 @@ bool LuaLvglManager::callRefs(lua_State *L)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LuaScriptManager::createTelemetryQueue()
|
||||
{
|
||||
if (luaInputTelemetryFifo == nullptr) {
|
||||
luaInputTelemetryFifo = new TelemetryQueue();
|
||||
registerTelemetryQueue(luaInputTelemetryFifo);
|
||||
}
|
||||
}
|
||||
|
||||
LuaScriptManager::~LuaScriptManager()
|
||||
{
|
||||
if (luaInputTelemetryFifo == nullptr) {
|
||||
deregisterTelemetryQueue(luaInputTelemetryFifo);
|
||||
delete luaInputTelemetryFifo;
|
||||
luaInputTelemetryFifo = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
+40
-30
@@ -28,6 +28,7 @@
|
||||
#include "lua_states.h"
|
||||
#include "lua_api.h"
|
||||
#include "lua_lvgl_widget.h"
|
||||
#include "telemetry/telemetry.h"
|
||||
|
||||
#include "edgetx_types.h"
|
||||
|
||||
@@ -35,10 +36,37 @@
|
||||
|
||||
class LuaWidgetFactory;
|
||||
|
||||
class LuaLvglManager
|
||||
class LuaEventHandler
|
||||
{
|
||||
public:
|
||||
LuaEventHandler() = default;
|
||||
void setupHandler(Window* w);
|
||||
void removeHandler(Window* w);
|
||||
|
||||
protected:
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
// "tap" handling
|
||||
static uint32_t downTime;
|
||||
static uint32_t tapTime;
|
||||
static uint32_t tapCount;
|
||||
// "swipe" / "slide" handling
|
||||
static tmr10ms_t swipeTimeOut;
|
||||
static bool _sliding;
|
||||
static coord_t _startX;
|
||||
static coord_t _startY;
|
||||
#endif
|
||||
static void event_cb(lv_event_t* e);
|
||||
|
||||
void onClickedEvent();
|
||||
void onCancelEvent();
|
||||
void onLuaEvent(event_t event);
|
||||
};
|
||||
|
||||
class LuaScriptManager : public LuaEventHandler
|
||||
{
|
||||
public:
|
||||
LuaLvglManager() = default;
|
||||
LuaScriptManager() = default;
|
||||
~LuaScriptManager();
|
||||
|
||||
std::vector<int> getLvglObjectRefs() const { return lvglObjectRefs; }
|
||||
void saveLvglObjectRef(int ref);
|
||||
@@ -62,46 +90,26 @@ class LuaLvglManager
|
||||
|
||||
uint8_t refreshInstructionsPercent;
|
||||
|
||||
void createTelemetryQueue();
|
||||
TelemetryQueue* telemetryQueue() { return luaInputTelemetryFifo; }
|
||||
|
||||
protected:
|
||||
int luaScriptContextRef = 0;
|
||||
std::vector<int> lvglObjectRefs;
|
||||
LvglWidgetObjectBase* tempParent = nullptr;
|
||||
};
|
||||
|
||||
class LuaEventHandler
|
||||
{
|
||||
public:
|
||||
LuaEventHandler() = default;
|
||||
void setupHandler(Window* w);
|
||||
void removeHandler(Window* w);
|
||||
|
||||
protected:
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
// "tap" handling
|
||||
static uint32_t downTime;
|
||||
static uint32_t tapTime;
|
||||
static uint32_t tapCount;
|
||||
// "swipe" / "slide" handling
|
||||
static tmr10ms_t swipeTimeOut;
|
||||
static bool _sliding;
|
||||
static coord_t _startX;
|
||||
static coord_t _startY;
|
||||
#if defined(LUA)
|
||||
TelemetryQueue* luaInputTelemetryFifo = nullptr;
|
||||
#endif
|
||||
static void event_cb(lv_event_t* e);
|
||||
|
||||
void onClicked();
|
||||
void onCancel();
|
||||
void onLuaEvent(event_t event);
|
||||
};
|
||||
|
||||
class LuaWidget : public Widget, public LuaEventHandler, public LuaLvglManager
|
||||
class LuaWidget : public Widget, public LuaScriptManager
|
||||
{
|
||||
friend class LuaWidgetFactory;
|
||||
|
||||
public:
|
||||
LuaWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect,
|
||||
WidgetPersistentData* persistentData, int luaScriptContextRef, int zoneRectDataRef,
|
||||
int optionsDataRef);
|
||||
WidgetPersistentData* persistentData, int zoneRectDataRef,
|
||||
int optionsDataRef, int createFunctionRef, std::string path);
|
||||
~LuaWidget() override;
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
@@ -160,3 +168,5 @@ class LuaWidget : public Widget, public LuaEventHandler, public LuaLvglManager
|
||||
|
||||
static void redraw_cb(lv_event_t *e);
|
||||
};
|
||||
|
||||
extern LuaScriptManager* luaScriptManager;
|
||||
|
||||
@@ -24,18 +24,26 @@
|
||||
|
||||
#include "lua_api.h"
|
||||
#include "lua_states.h"
|
||||
#include "strhelpers.h"
|
||||
|
||||
#define MAX_INSTRUCTIONS (20000/100)
|
||||
|
||||
LuaWidgetFactory::LuaWidgetFactory(const char* name, ZoneOption* widgetOptions,
|
||||
int createFunction) :
|
||||
LuaWidgetFactory::LuaWidgetFactory(const char* name, ZoneOption* widgetOptions, int optionDefinitionsReference,
|
||||
int createFunction, int updateFunction, int refreshFunction,
|
||||
int backgroundFunction, int translateFunction, bool lvglLayout,
|
||||
const char* filename) :
|
||||
WidgetFactory(name, widgetOptions),
|
||||
optionDefinitionsReference(optionDefinitionsReference),
|
||||
createFunction(createFunction),
|
||||
updateFunction(0),
|
||||
refreshFunction(0),
|
||||
backgroundFunction(0),
|
||||
translateFunction(0)
|
||||
updateFunction(updateFunction),
|
||||
refreshFunction(refreshFunction),
|
||||
backgroundFunction(backgroundFunction),
|
||||
translateFunction(translateFunction),
|
||||
lvglLayout(lvglLayout),
|
||||
path(filename)
|
||||
{
|
||||
path = path.substr(0, path.rfind("/") + 1);
|
||||
translateOptions(widgetOptions);
|
||||
}
|
||||
|
||||
LuaWidgetFactory::~LuaWidgetFactory() {
|
||||
@@ -45,7 +53,7 @@ LuaWidgetFactory::~LuaWidgetFactory() {
|
||||
delete displayName;
|
||||
}
|
||||
|
||||
auto option = getOptions();
|
||||
auto option = getDefaultOptions();
|
||||
while (option && option->name != nullptr) {
|
||||
if (option->displayName) {
|
||||
delete option->displayName;
|
||||
@@ -62,7 +70,6 @@ Widget* LuaWidgetFactory::create(Window* parent, const rect_t& rect,
|
||||
initPersistentData(persistentData, init);
|
||||
|
||||
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, createFunction);
|
||||
|
||||
// Make 'zone' table for 'create' call
|
||||
lua_newtable(lsWidgets);
|
||||
@@ -75,8 +82,6 @@ Widget* LuaWidgetFactory::create(Window* parent, const rect_t& rect,
|
||||
|
||||
// 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);
|
||||
@@ -99,14 +104,8 @@ Widget* LuaWidgetFactory::create(Window* parent, const rect_t& rect,
|
||||
|
||||
// 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, optionsDataRef);
|
||||
if (err) lw->setErrorMessage("create()");
|
||||
return lw;
|
||||
return new LuaWidget(this, parent, rect, persistentData, zoneRectDataRef, optionsDataRef, createFunction, path);
|
||||
}
|
||||
|
||||
void LuaWidgetFactory::translateOptions(ZoneOption * options)
|
||||
@@ -144,3 +143,207 @@ void LuaWidgetFactory::translateOptions(ZoneOption * options)
|
||||
}
|
||||
lua_pop(lsWidgets, 1);
|
||||
}
|
||||
|
||||
static int switchValue()
|
||||
{
|
||||
int v = SWSRC_INVERT;
|
||||
if (lua_istable(lsWidgets, -1)) {
|
||||
// Find first available
|
||||
int t = lua_gettop(lsWidgets);
|
||||
for (lua_pushnil(lsWidgets); v == SWSRC_INVERT && lua_next(lsWidgets, -2); lua_pop(lsWidgets, 1)) {
|
||||
v = getSwitchIndex(luaL_checkstring(lsWidgets, -1), false);
|
||||
}
|
||||
lua_settop(lsWidgets, t);
|
||||
} else if (lua_type(lsWidgets, -1) == LUA_TSTRING) {
|
||||
v = getSwitchIndex(lua_tostring(lsWidgets, -1), true);
|
||||
} else {
|
||||
v = luaL_checkinteger(lsWidgets, -1);
|
||||
}
|
||||
if (v == SWSRC_INVERT) v = SWSRC_NONE;
|
||||
return v;
|
||||
}
|
||||
|
||||
static int sourceValue()
|
||||
{
|
||||
int v = -1;
|
||||
if (lua_istable(lsWidgets, -1)) {
|
||||
// Find first available
|
||||
int t = lua_gettop(lsWidgets);
|
||||
for (lua_pushnil(lsWidgets); v < 0 && lua_next(lsWidgets, -2); lua_pop(lsWidgets, 1)) {
|
||||
v = getSourceIndex(luaL_checkstring(lsWidgets, -1), false);
|
||||
}
|
||||
lua_settop(lsWidgets, t);
|
||||
} else if (lua_type(lsWidgets, -1) == LUA_TSTRING) {
|
||||
v = getSourceIndex(lua_tostring(lsWidgets, -1), true);
|
||||
} else {
|
||||
v = luaL_checkunsigned(lsWidgets, -1);
|
||||
}
|
||||
if (v == -1) v = MIXSRC_NONE;
|
||||
return v;
|
||||
}
|
||||
|
||||
// Parse the options table to get the default, min and max values
|
||||
// Called when the widget settings dialog is opened to get values
|
||||
// for current loaded model.
|
||||
const void LuaWidgetFactory::parseOptionDefaults() const
|
||||
{
|
||||
if (optionDefinitionsReference == LUA_REFNIL) {
|
||||
// TRACE("parseOptionDefaults() no options");
|
||||
return;
|
||||
}
|
||||
|
||||
PROTECT_LUA()
|
||||
{
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, optionDefinitionsReference);
|
||||
ZoneOption *option = (ZoneOption*)options;
|
||||
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2), option->name;
|
||||
lua_pop(lsWidgets, 1)) {
|
||||
// TRACE("parsing option %d", count);
|
||||
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
|
||||
luaL_checktype(lsWidgets, -1, LUA_TTABLE); // value is table
|
||||
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 2:
|
||||
if (option->type == ZoneOption::Switch) {
|
||||
option->deflt.signedValue = switchValue();
|
||||
} else if (option->type == ZoneOption::Source) {
|
||||
option->deflt.unsignedValue = sourceValue();
|
||||
} else if (option->type == ZoneOption::Integer) {
|
||||
option->deflt.signedValue = luaL_checkinteger(lsWidgets, -1);
|
||||
} else if (option->type == ZoneOption::Bool) {
|
||||
option->deflt.boolValue = (luaL_checkunsigned(lsWidgets, -1) != 0);
|
||||
} else if (option->type == ZoneOption::String || option->type == ZoneOption::File) {
|
||||
strncpy(option->deflt.stringValue, luaL_checkstring(lsWidgets, -1),
|
||||
LEN_ZONE_OPTION_STRING);
|
||||
} else {
|
||||
option->deflt.unsignedValue = luaL_checkunsigned(lsWidgets, -1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (option->type == ZoneOption::Switch) {
|
||||
option->min.signedValue = switchValue();
|
||||
} else if (option->type == ZoneOption::Source) {
|
||||
option->min.unsignedValue = sourceValue();
|
||||
} else if (option->type == ZoneOption::Integer || option->type == ZoneOption::Slider) {
|
||||
option->min.signedValue = luaL_checkinteger(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(luaL_checkstring(lsWidgets, -1));
|
||||
}
|
||||
} else if (option->type == ZoneOption::File) {
|
||||
option->fileSelectPath = luaL_checkstring(lsWidgets, -1);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (option->type == ZoneOption::Switch) {
|
||||
option->max.signedValue = switchValue();
|
||||
} else if (option->type == ZoneOption::Source) {
|
||||
option->max.unsignedValue = sourceValue();
|
||||
} else if (option->type == ZoneOption::Integer || option->type == ZoneOption::Slider) {
|
||||
option->max.signedValue = luaL_checkinteger(lsWidgets, -1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
option++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("error in theme/widget options");
|
||||
}
|
||||
UNPROTECT_LUA();
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse options table to get name and type values.
|
||||
// Called on radio startup to build base data for all widgtes.
|
||||
ZoneOption* LuaWidgetFactory::parseOptionDefinitions(int reference)
|
||||
{
|
||||
if (reference == LUA_REFNIL) {
|
||||
// TRACE("parseOptionDefinitions() no options");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, reference);
|
||||
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2); lua_pop(lsWidgets, 1)) {
|
||||
count++;
|
||||
}
|
||||
|
||||
// TRACE("we have %d options", count);
|
||||
if (count > MAX_WIDGET_OPTIONS) {
|
||||
count = MAX_WIDGET_OPTIONS;
|
||||
// TRACE("limited to %d options", count);
|
||||
}
|
||||
|
||||
ZoneOption *options = new ZoneOption[count + 1];
|
||||
if (!options) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PROTECT_LUA()
|
||||
{
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, reference);
|
||||
ZoneOption *option = options;
|
||||
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2), count-- > 0;
|
||||
lua_pop(lsWidgets, 1)) {
|
||||
// TRACE("parsing option %d", count);
|
||||
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
|
||||
luaL_checktype(lsWidgets, -1, LUA_TTABLE); // value is table
|
||||
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:
|
||||
option->name = luaL_checkstring(lsWidgets, -1);
|
||||
option->displayName = nullptr;
|
||||
// TRACE("name = %s", option->name);
|
||||
break;
|
||||
case 1:
|
||||
option->type = (ZoneOption::Type)luaL_checkinteger(lsWidgets, -1);
|
||||
option->deflt.unsignedValue = 0;
|
||||
// set some sensible defaults
|
||||
if (option->type == ZoneOption::Integer) {
|
||||
option->min.signedValue = -100;
|
||||
option->max.signedValue = 100;
|
||||
} else if (option->type == ZoneOption::Switch) {
|
||||
option->min.signedValue = SWSRC_FIRST;
|
||||
option->max.signedValue = SWSRC_LAST;
|
||||
} else if (option->type == ZoneOption::Timer) {
|
||||
option->min.unsignedValue = 0;
|
||||
option->max.unsignedValue = MAX_TIMERS - 1;
|
||||
} else if (option->type == ZoneOption::TextSize) {
|
||||
option->min.unsignedValue = FONT_STD_INDEX;
|
||||
option->max.unsignedValue = FONTS_COUNT - 1;
|
||||
} else if (option->type == ZoneOption::String || option->type == ZoneOption::File) {
|
||||
option->deflt.stringValue[0] = 0;
|
||||
} else if (option->type == ZoneOption::Slider) {
|
||||
option->min.unsignedValue = 0;
|
||||
option->max.unsignedValue = 9;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
option++;
|
||||
}
|
||||
option->name = NULL; // sentinel
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("error in theme/widget options");
|
||||
delete[] options;
|
||||
return NULL;
|
||||
}
|
||||
UNPROTECT_LUA();
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
|
||||
class LuaWidgetFactory : public WidgetFactory
|
||||
{
|
||||
friend void luaLoadWidgetCallback();
|
||||
friend class LuaWidget;
|
||||
|
||||
public:
|
||||
LuaWidgetFactory(const char* name, ZoneOption* widgetOptions,
|
||||
int createFunction);
|
||||
LuaWidgetFactory(const char* name, ZoneOption* widgetOptions, int optionDefinitionsReference,
|
||||
int createFunction, int updateFunction, int refreshFunction,
|
||||
int backgroundFunction, int translateFunction, bool lvgllayout,
|
||||
const char* filename);
|
||||
~LuaWidgetFactory();
|
||||
|
||||
Widget* create(Window* parent, const rect_t& rect,
|
||||
@@ -41,14 +42,18 @@ class LuaWidgetFactory : public WidgetFactory
|
||||
|
||||
bool useLvglLayout() const { return lvglLayout; }
|
||||
|
||||
static ZoneOption* parseOptionDefinitions(int reference);
|
||||
const void parseOptionDefaults() const override;
|
||||
|
||||
protected:
|
||||
void translateOptions(ZoneOption * options);
|
||||
|
||||
int optionDefinitionsReference;
|
||||
int createFunction;
|
||||
int updateFunction;
|
||||
int refreshFunction;
|
||||
int backgroundFunction;
|
||||
int translateFunction;
|
||||
int settingsFunction;
|
||||
bool lvglLayout;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
+13
-133
@@ -98,123 +98,12 @@ void luaSetInstructionsLimit(lua_State * L, int count)
|
||||
#endif
|
||||
}
|
||||
|
||||
ZoneOption *createOptionsArray(int reference, uint8_t maxOptions)
|
||||
{
|
||||
if (reference == 0) {
|
||||
// TRACE("createOptionsArray() no options");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, reference);
|
||||
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2); lua_pop(lsWidgets, 1)) {
|
||||
count++;
|
||||
}
|
||||
|
||||
// TRACE("we have %d options", count);
|
||||
if (count > maxOptions) {
|
||||
count = maxOptions;
|
||||
// TRACE("limited to %d options", count);
|
||||
}
|
||||
|
||||
ZoneOption *options = new ZoneOption[count + 1];
|
||||
if (!options) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PROTECT_LUA()
|
||||
{
|
||||
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, reference);
|
||||
ZoneOption *option = options;
|
||||
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2), count-- > 0;
|
||||
lua_pop(lsWidgets, 1)) {
|
||||
// TRACE("parsing option %d", count);
|
||||
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
|
||||
luaL_checktype(lsWidgets, -1, LUA_TTABLE); // value is table
|
||||
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:
|
||||
option->name = luaL_checkstring(lsWidgets, -1);
|
||||
option->displayName = nullptr;
|
||||
// TRACE("name = %s", option->name);
|
||||
break;
|
||||
case 1:
|
||||
option->type = (ZoneOption::Type)luaL_checkinteger(lsWidgets, -1);
|
||||
option->deflt.unsignedValue = 0;
|
||||
// set some sensible defaults
|
||||
if (option->type == ZoneOption::Integer) {
|
||||
option->min.signedValue = -100;
|
||||
option->max.signedValue = 100;
|
||||
} else if (option->type == ZoneOption::Switch) {
|
||||
option->min.signedValue = SWSRC_FIRST;
|
||||
option->max.signedValue = SWSRC_LAST;
|
||||
} else if (option->type == ZoneOption::Timer) {
|
||||
option->min.unsignedValue = 0;
|
||||
option->max.unsignedValue = MAX_TIMERS - 1;
|
||||
} else if (option->type == ZoneOption::TextSize) {
|
||||
option->min.unsignedValue = FONT_STD_INDEX;
|
||||
option->max.unsignedValue = FONTS_COUNT - 1;
|
||||
} else if (option->type == ZoneOption::String || option->type == ZoneOption::File) {
|
||||
option->deflt.stringValue[0] = 0;
|
||||
} else if (option->type == ZoneOption::Slider) {
|
||||
option->min.unsignedValue = 0;
|
||||
option->max.unsignedValue = 9;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch) {
|
||||
option->deflt.signedValue = luaL_checkinteger(lsWidgets, -1);
|
||||
} else if (option->type == ZoneOption::Bool) {
|
||||
option->deflt.boolValue = (luaL_checkunsigned(lsWidgets, -1) != 0);
|
||||
} else if (option->type == ZoneOption::String || option->type == ZoneOption::File) {
|
||||
strncpy(option->deflt.stringValue, luaL_checkstring(lsWidgets, -1),
|
||||
LEN_ZONE_OPTION_STRING);
|
||||
} else {
|
||||
option->deflt.unsignedValue = luaL_checkunsigned(lsWidgets, -1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch || option->type == ZoneOption::Slider) {
|
||||
option->min.signedValue = luaL_checkinteger(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(luaL_checkstring(lsWidgets, -1));
|
||||
}
|
||||
} else if (option->type == ZoneOption::File) {
|
||||
option->fileSelectPath = luaL_checkstring(lsWidgets, -1);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch || option->type == ZoneOption::Slider) {
|
||||
option->max.signedValue = luaL_checkinteger(lsWidgets, -1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
option++;
|
||||
}
|
||||
option->name = NULL; // sentinel
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("error in theme/widget options");
|
||||
delete[] options;
|
||||
return NULL;
|
||||
}
|
||||
UNPROTECT_LUA();
|
||||
return options;
|
||||
}
|
||||
|
||||
void luaLoadWidgetCallback()
|
||||
void luaLoadWidgetCallback(const char* filename)
|
||||
{
|
||||
TRACE("luaLoadWidgetCallback()");
|
||||
const char * name=NULL;
|
||||
|
||||
int widgetOptions = 0, createFunction = 0, updateFunction = 0, settingsFunction = 0,
|
||||
int optionDefinitionsReference = LUA_REFNIL, createFunction = 0, updateFunction = 0,
|
||||
refreshFunction = 0, backgroundFunction = 0, translateFunction = 0;
|
||||
bool lvglLayout = false;
|
||||
|
||||
@@ -226,7 +115,7 @@ void luaLoadWidgetCallback()
|
||||
name = luaL_checkstring(lsWidgets, -1);
|
||||
}
|
||||
else if (!strcmp(key, "options")) {
|
||||
widgetOptions = luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
|
||||
optionDefinitionsReference = luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
|
||||
lua_pushnil(lsWidgets);
|
||||
}
|
||||
else if (!strcmp(key, "create")) {
|
||||
@@ -249,34 +138,25 @@ void luaLoadWidgetCallback()
|
||||
translateFunction = luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
|
||||
lua_pushnil(lsWidgets);
|
||||
}
|
||||
else if (!strcmp(key, "settings")) {
|
||||
settingsFunction = luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
|
||||
lua_pushnil(lsWidgets);
|
||||
}
|
||||
else if (!strcasecmp(key, "useLvgl")) {
|
||||
lvglLayout = lua_toboolean(lsWidgets, -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (name && createFunction) {
|
||||
ZoneOption * options = createOptionsArray(widgetOptions, MAX_WIDGET_OPTIONS);
|
||||
ZoneOption * options = LuaWidgetFactory::parseOptionDefinitions(optionDefinitionsReference);
|
||||
if (options) {
|
||||
LuaWidgetFactory * factory = new LuaWidgetFactory(name, options, createFunction);
|
||||
factory->updateFunction = updateFunction;
|
||||
factory->refreshFunction = refreshFunction;
|
||||
factory->backgroundFunction = backgroundFunction;
|
||||
factory->translateFunction = translateFunction;
|
||||
factory->settingsFunction = settingsFunction;
|
||||
factory->translateOptions(options);
|
||||
factory->lvglLayout = lvglLayout;
|
||||
new LuaWidgetFactory(name, options, optionDefinitionsReference,
|
||||
createFunction, updateFunction, refreshFunction, backgroundFunction,
|
||||
translateFunction, lvglLayout, filename);
|
||||
TRACE("Loaded Lua widget %s", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void luaLoadFile(const char * filename, void (*callback)())
|
||||
static void luaLoadFile(const char * filename, std::function<void()> callback)
|
||||
{
|
||||
if (lsWidgets == NULL || callback == NULL)
|
||||
if (lsWidgets == NULL)
|
||||
return;
|
||||
|
||||
TRACE("luaLoadFile(%s)", filename);
|
||||
@@ -286,7 +166,7 @@ void luaLoadFile(const char * filename, void (*callback)())
|
||||
PROTECT_LUA() {
|
||||
if (luaLoadScriptFileToState(lsWidgets, filename, LUA_SCRIPT_LOAD_MODE) == SCRIPT_OK) {
|
||||
if (lua_pcall(lsWidgets, 0, 1, 0) == LUA_OK && lua_istable(lsWidgets, -1)) {
|
||||
(*callback)();
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
TRACE("luaLoadFile(%s): Error parsing script: %s", filename, lua_tostring(lsWidgets, -1));
|
||||
@@ -301,7 +181,7 @@ void luaLoadFile(const char * filename, void (*callback)())
|
||||
UNPROTECT_LUA();
|
||||
}
|
||||
|
||||
void luaLoadFiles(const char * directory, void (*callback)())
|
||||
static void luaLoadFiles(const char * directory)
|
||||
{
|
||||
char path[LUA_FULLPATH_MAXLEN+1];
|
||||
FILINFO fno;
|
||||
@@ -324,7 +204,7 @@ void luaLoadFiles(const char * directory, void (*callback)())
|
||||
strcpy(&path[pathlen], fno.fname);
|
||||
strcat(&path[pathlen], LUA_WIDGET_FILENAME);
|
||||
if (isFileAvailable(path)) {
|
||||
luaLoadFile(path, callback);
|
||||
luaLoadFile(path, [=]() { luaLoadWidgetCallback(path); });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,7 +254,7 @@ void luaInitThemesAndWidgets()
|
||||
}
|
||||
UNPROTECT_LUA();
|
||||
TRACE("lsWidgets %p", lsWidgets);
|
||||
luaLoadFiles(WIDGETS_PATH, luaLoadWidgetCallback);
|
||||
luaLoadFiles(WIDGETS_PATH);
|
||||
luaDoGc(lsWidgets, true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user