* Store 'zone' rectangle dat in Lua registry and update it when the screen layout changes or full screen mode changes. Allows Lua widgets to adjust to layout changes. * Call widget 'update' function is layout has changed.
150 lines
4.4 KiB
C++
150 lines
4.4 KiB
C++
/*
|
|
* Copyright (C) EdgeTX
|
|
*
|
|
* Based on code named
|
|
* opentx - https://github.com/opentx/opentx
|
|
* th9x - http://code.google.com/p/th9x
|
|
* er9x - http://code.google.com/p/er9x
|
|
* gruvin9x - http://code.google.com/p/gruvin9x
|
|
*
|
|
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "lua_widget_factory.h"
|
|
#include "lua_widget.h"
|
|
|
|
#include "lua_api.h"
|
|
|
|
#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),
|
|
createFunction(createFunction),
|
|
updateFunction(0),
|
|
refreshFunction(0),
|
|
backgroundFunction(0),
|
|
translateFunction(0)
|
|
{
|
|
}
|
|
|
|
LuaWidgetFactory::~LuaWidgetFactory() {
|
|
unregisterWidget(this);
|
|
|
|
if (displayName) {
|
|
delete displayName;
|
|
}
|
|
|
|
auto option = getOptions();
|
|
while (option && option->name != nullptr) {
|
|
if (option->displayName) {
|
|
delete option->displayName;
|
|
}
|
|
option++;
|
|
}
|
|
}
|
|
|
|
Widget* LuaWidgetFactory::create(Window* parent, const rect_t& rect,
|
|
Widget::PersistentData* persistentData,
|
|
bool init) const
|
|
{
|
|
if (lsWidgets == 0) return 0;
|
|
initPersistentData(persistentData, init);
|
|
|
|
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, createFunction);
|
|
|
|
// 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);
|
|
|
|
// 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);
|
|
|
|
lua_newtable(lsWidgets);
|
|
int i = 0;
|
|
for (const ZoneOption* option = options; option->name; option++, i++) {
|
|
if (option->type == ZoneOption::String) {
|
|
lua_pushstring(lsWidgets, option->name);
|
|
// Zero-terminated string for Lua
|
|
char str[LEN_ZONE_OPTION_STRING + 1] = {0};
|
|
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.signedValue;
|
|
l_pushtableint(option->name, COLOR2FLAGS(value) | RGB_FLAG);
|
|
} else {
|
|
int32_t value = persistentData->options[i].value.signedValue;
|
|
l_pushtableint(option->name, value);
|
|
}
|
|
}
|
|
|
|
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);
|
|
if (err) lw->setErrorMessage("create()");
|
|
return lw;
|
|
}
|
|
|
|
|
|
void LuaWidgetFactory::translateOptions(ZoneOption * options)
|
|
{
|
|
if (lsWidgets == 0) return;
|
|
|
|
// No translations provided
|
|
if (!translateFunction) return;
|
|
|
|
auto lang = TRANSLATIONS;
|
|
|
|
auto option = options;
|
|
while (option && option->name != nullptr) {
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, translateFunction);
|
|
lua_pushstring(lsWidgets, option->name);
|
|
lua_pushstring(lsWidgets, lang);
|
|
bool err = lua_pcall(lsWidgets, 2, 1, 0);
|
|
if (!err) {
|
|
auto dn = lua_tostring(lsWidgets, -1);
|
|
if (dn) option->displayName = strdup(dn);
|
|
}
|
|
lua_pop(lsWidgets, 1);
|
|
|
|
option++;
|
|
}
|
|
|
|
// Widget display name
|
|
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, translateFunction);
|
|
lua_pushstring(lsWidgets, name);
|
|
lua_pushstring(lsWidgets, lang);
|
|
bool err = lua_pcall(lsWidgets, 2, 1, 0);
|
|
if (!err) {
|
|
auto dn = lua_tostring(lsWidgets, -1);
|
|
if (dn) displayName = strdup(dn);
|
|
}
|
|
lua_pop(lsWidgets, 1);
|
|
}
|