Skip to content

Commit

Permalink
feat(lua): support for using LVGL objects on colorlcd (#4887)
Browse files Browse the repository at this point in the history
  • Loading branch information
philmoz authored Jun 13, 2024
1 parent 22128df commit b4e33fc
Show file tree
Hide file tree
Showing 30 changed files with 2,257 additions and 123 deletions.
1 change: 1 addition & 0 deletions radio/src/gui/colorlcd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ if(LUA)
lua/lua_widget.cpp
lua/lua_widget_factory.cpp
lua/widgets.cpp
lua/lua_lvgl_widget.cpp
)
endif()

Expand Down
3 changes: 0 additions & 3 deletions radio/src/gui/colorlcd/layouts/layout_factory_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ void Layout::adjustLayout()

// Save settings
decorationSettings = checkSettings;

// Set visible decoration
show();
}

void Layout::show(bool visible)
Expand Down
3 changes: 1 addition & 2 deletions radio/src/gui/colorlcd/model_select.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class ModelButton : public Button
if (modelLayouts[layout].hasImage) {
if (modelCell->modelBitmap[0]) {
GET_FILENAME(filename, BITMAPS_PATH, modelCell->modelBitmap, "");
auto bitmap = new StaticImage(this, {PAD_TINY, PAD_TINY, w, h}, filename, true);
auto bitmap = new StaticImage(this, {PAD_TINY, PAD_TINY, w, h}, filename, false, true);
lv_obj_move_background(bitmap->getLvObj());
bitmap->show(bitmap->hasImage());
if (bitmap->hasImage()) {
Expand Down Expand Up @@ -626,7 +626,6 @@ void ModelLabelsWindow::newModel()
snprintf(path + len, LEN_BUFFER - len, "/%s%s", name.c_str(), SCRIPT_EXT);
if (f_stat(path, 0) == FR_OK) {
luaExec(path);
StandaloneLuaWindow::instance()->attach();
}
#endif
}
Expand Down
1 change: 0 additions & 1 deletion radio/src/gui/colorlcd/radio_sdmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,6 @@ void RadioSdManagerPage::fileAction(const char* path, const char* name,
else if (isExtensionMatching(ext, SCRIPTS_EXT)) {
menu->addLine(STR_EXECUTE_FILE, [=]() {
luaExec(fullpath);
StandaloneLuaWindow::instance()->attach();
});
}
#endif
Expand Down
2 changes: 0 additions & 2 deletions radio/src/gui/colorlcd/radio_tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ static void run_lua_tool(Window* parent, const std::string& path)
f_chdir(toolPath);

luaExec(path.c_str());
auto lua_win = StandaloneLuaWindow::instance();
lua_win->attach();
}

// LUA scripts in TOOLS
Expand Down
117 changes: 97 additions & 20 deletions radio/src/gui/colorlcd/standalone_lua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,33 +85,52 @@ void StandaloneLuaWindow::redraw_cb(lv_event_t* e)
// singleton instance
StandaloneLuaWindow* StandaloneLuaWindow::_instance;

StandaloneLuaWindow::StandaloneLuaWindow() :
Window(nullptr, {0, 0, LCD_W, LCD_H}),
StandaloneLuaWindow::StandaloneLuaWindow(bool useLvgl) :
Window(MainWindow::instance(), {0, 0, LCD_W, LCD_H}),
useLvgl(useLvgl),
lcdBuffer(BMP_RGB565, LCD_W, LCD_H),
popup({50, 73, LCD_W - 100, LCD_H - 146})
{
setWindowFlag(OPAQUE);

etx_solid_bg(lvobj);

lcdBuffer.clear();
lcdBuffer.drawText(LCD_W / 2, LCD_H / 2 - 20, STR_LOADING,
FONT(L) | COLOR_THEME_PRIMARY2 | CENTERED);
lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
if (useLvglLayout()) {
padAll(PAD_ZERO);
etx_scrollbar(lvobj);
lv_obj_t* lbl = lv_label_create(lvobj);
lv_obj_set_pos(lbl, 0, 0);
lv_obj_set_size(lbl, LCD_W, LCD_H);
etx_solid_bg(lbl, COLOR_THEME_PRIMARY1_INDEX);
etx_txt_color(lbl, COLOR_THEME_PRIMARY2_INDEX);
lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
lv_obj_set_style_pad_top(lbl, (LCD_H - EdgeTxStyles::PAGE_LINE_HEIGHT) / 2, LV_PART_MAIN);
lv_label_set_text(lbl, STR_LOADING);

luaLvglManager = this;
} else {
lcdBuffer.clear();
lcdBuffer.drawText(LCD_W / 2, LCD_H / 2 - 20, STR_LOADING,
FONT(L) | COLOR_THEME_PRIMARY2 | CENTERED);
lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICK_FOCUSABLE);

lv_obj_add_event_cb(lvobj, StandaloneLuaWindow::redraw_cb, LV_EVENT_DRAW_MAIN, nullptr);
}

// setup LUA event handler
setupHandler(this);

lv_obj_add_event_cb(lvobj, StandaloneLuaWindow::redraw_cb, LV_EVENT_DRAW_MAIN, nullptr);
attach();
}

StandaloneLuaWindow* StandaloneLuaWindow::instance()
void StandaloneLuaWindow::setup(bool useLvgl)
{
if (!_instance) {
_instance = new StandaloneLuaWindow();
}
_instance = new StandaloneLuaWindow(useLvgl);
}

StandaloneLuaWindow* StandaloneLuaWindow::instance()
{
return _instance;
}

Expand All @@ -121,24 +140,26 @@ void StandaloneLuaWindow::attach()
// backup previous screen
prevScreen = lv_scr_act();

// and load new one
lv_scr_load(lvobj);

Layer::back()->hide();
Layer::push(this);

lv_group_add_obj(lv_group_get_default(), lvobj);
lv_group_set_editing(lv_group_get_default(), true);
if (!useLvglLayout()) {
lv_group_add_obj(lv_group_get_default(), lvobj);
lv_group_set_editing(lv_group_get_default(), true);
}
}
}

void StandaloneLuaWindow::deleteLater(bool detach, bool trash)
{
if (_deleted) return;

luaLvglManager = nullptr;

Layer::pop(this);
Layer::back()->show();

if (prevScreen) {
lv_scr_load(prevScreen);
prevScreen = nullptr;
}

Expand All @@ -159,8 +180,20 @@ void StandaloneLuaWindow::checkEvents()
if (luaState != INTERPRETER_RELOAD_PERMANENT_SCRIPTS) {
// if LUA finished a full cycle,
// invalidate to display the screen buffer
bool useLvgl = useLvglLayout();
if (luaTask(true)) {
invalidate();
if (useLvgl && !hasError) {
PROTECT_LUA() {
if (!callRefs(lsScripts)) {
luaShowError();
}
} else {
luaShowError();
}
UNPROTECT_LUA();
} else {
invalidate();
}
}
}

Expand All @@ -174,7 +207,7 @@ void StandaloneLuaWindow::checkEvents()
luaLcdBuffer = nullptr;
}

void StandaloneLuaWindow::onClicked() { LuaEventHandler::onClicked(); }
void StandaloneLuaWindow::onClicked() { Keyboard::hide(false); LuaEventHandler::onClicked(); }

void StandaloneLuaWindow::onCancel() { LuaEventHandler::onCancel(); }

Expand Down Expand Up @@ -210,3 +243,47 @@ bool StandaloneLuaWindow::displayPopup(event_t event, uint8_t type,

return false;
}

void StandaloneLuaWindow::clear()
{
clearRefs(lsScripts);
Window::clear();
}

void StandaloneLuaWindow::luaShowError()
{
hasError = true;
extern void luaError(lua_State *L, uint8_t error);
luaError(lsScripts, SCRIPT_SYNTAX_ERROR);
}

void StandaloneLuaWindow::showError(bool firstCall, const char* title, const char* msg)
{
hasError = true;
if (!errorModal) {
lv_obj_set_scroll_dir(lvobj, LV_DIR_NONE);
errorModal = lv_obj_create(lvobj);
lv_obj_set_pos(errorModal, lv_obj_get_scroll_x(lvobj), lv_obj_get_scroll_y(lvobj));
lv_obj_set_size(errorModal, LCD_W, LCD_H);
etx_bg_color(errorModal, COLOR_BLACK_INDEX);
etx_obj_add_style(errorModal, styles->bg_opacity_75, LV_PART_MAIN);
errorTitle = lv_label_create(errorModal);
lv_obj_set_pos(errorTitle, 50, 30);
lv_obj_set_size(errorTitle, LCD_W - 100, 32);
etx_txt_color(errorTitle, COLOR_THEME_PRIMARY2_INDEX);
etx_solid_bg(errorTitle, COLOR_THEME_SECONDARY1_INDEX);
etx_font(errorTitle, FONT_L_INDEX);
etx_obj_add_style(errorTitle, styles->text_align_center, LV_PART_MAIN);
errorMsg = lv_label_create(errorModal);
lv_obj_set_pos(errorMsg, 50, 62);
lv_obj_set_size(errorMsg, LCD_W - 100, LCD_H - 92);
lv_obj_set_style_pad_all(errorMsg, 4, LV_PART_MAIN);
etx_txt_color(errorMsg, COLOR_THEME_PRIMARY1_INDEX);
etx_solid_bg(errorMsg, COLOR_THEME_SECONDARY3_INDEX);
etx_font(errorMsg, FONT_STD_INDEX);
etx_obj_add_style(errorMsg, styles->text_align_center, LV_PART_MAIN);
}

lv_label_set_text(errorTitle, title);
lv_label_set_text(errorMsg, msg);
}
21 changes: 19 additions & 2 deletions radio/src/gui/colorlcd/standalone_lua.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ struct LuaPopup
void paint(BitmapBuffer* dc, uint8_t type, const char* text, const char* info);
};

class StandaloneLuaWindow : public Window, public LuaEventHandler
class StandaloneLuaWindow : public Window, public LuaEventHandler, public LuaLvglManager
{
static StandaloneLuaWindow* _instance;

explicit StandaloneLuaWindow();
explicit StandaloneLuaWindow(bool useLvgl);

public:
static StandaloneLuaWindow* instance();
static void setup(bool useLvgl);

void attach();
void deleteLater(bool detach = true, bool trash = true) override;
Expand All @@ -52,8 +53,24 @@ class StandaloneLuaWindow : public Window, public LuaEventHandler
bool displayPopup(event_t event, uint8_t type, const char* text,
const char* info, bool& result);

Window* getCurrentParent() const override { return tempParent ? tempParent : (Window*)this; }

void clear() override;
bool useLvglLayout() const override { return useLvgl; }

void luaShowError() override;

void showError(bool firstCall, const char* title, const char* msg);

bool isWidget() override { return false; }

protected:
lv_obj_t* prevScreen = nullptr;
lv_obj_t* errorModal = nullptr;
lv_obj_t* errorTitle = nullptr;
lv_obj_t* errorMsg = nullptr;
bool hasError = false;
bool useLvgl = false;

// GFX
BitmapBuffer lcdBuffer;
Expand Down
1 change: 1 addition & 0 deletions radio/src/gui/colorlcd/view_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class ViewMain : public NavWindow
bool onLongPress() override;

void show(bool visible = true) override;
bool viewIsVisible() const { return isVisible; }
void showTopBarEdgeTxButton();
void hideTopBarEdgeTxButton();

Expand Down
5 changes: 3 additions & 2 deletions radio/src/gui/colorlcd/widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,17 @@ void Widget::setFullscreen(bool enable)
}
// Enter Fullscreen Mode
else {
ViewMain::instance()->enableWidgetSelect(false);

// ViewMain hidden - re-show this widget
show();

// Set window opaque (inhibits redraw from windows below)
setWindowFlag(OPAQUE);

updateZoneRect(parent->getRect());
updateZoneRect(parent->getRect(), false);
setRect(parent->getRect());

ViewMain::instance()->enableWidgetSelect(false);
bringToTop();

if (!lv_obj_get_group(lvobj)) {
Expand Down
2 changes: 1 addition & 1 deletion radio/src/gui/colorlcd/widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class Widget : public ButtonBase
virtual void background() {}

// Update widget 'zone' data (for Lua widgets)
virtual void updateZoneRect(rect_t rect) {}
virtual void updateZoneRect(rect_t rect, bool updateUI = true) {}

void enableFocus(bool enable);

Expand Down
2 changes: 1 addition & 1 deletion radio/src/gui/colorlcd/widgets/timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class TimerWidget : public Widget

int val = lastValue;
if (lastStartValue && timerData.showElapsed &&
lastStartValue != lastValue)
(int)lastStartValue != lastValue)
val = (int)lastStartValue - lastValue;

if (isLarge) {
Expand Down
2 changes: 1 addition & 1 deletion radio/src/lua/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ add_custom_target(lua_mixsrc DEPENDS ${HW_DESC_JSON} lua_mixsrc.inc)
add_custom_target(lua_keys DEPENDS ${HW_DESC_JSON} lua_keys.inc)

if(GUI_DIR STREQUAL colorlcd)
set(SRC ${SRC} lua/api_colorlcd.cpp lua/widgets.cpp)
set(SRC ${SRC} lua/api_colorlcd.cpp lua/api_colorlcd_lvgl.cpp lua/widgets.cpp)
else()
set(SRC ${SRC} lua/api_stdlcd.cpp)
endif()
Expand Down
11 changes: 6 additions & 5 deletions radio/src/lua/api_colorlcd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,18 @@
#include "theme.h"

#include "lua_api.h"
#include "lua_widget.h"
#include "api_colorlcd.h"

#define BITMAP_METATABLE "BITMAP*"

constexpr coord_t INVERT_BOX_MARGIN = 2;
constexpr int8_t text_horizontal_offset[7] {-2,-1,-2,-2,-2,-2,-2};
constexpr int8_t text_vertical_offset[7] {0,0,0,0,0,-1,7};
constexpr int8_t text_horizontal_offset[7] = {-2,-1,-2,-2,-2,-2,-2};
constexpr int8_t text_vertical_offset[7] = {0,0,0,0,0,-1,7};

BitmapBuffer* luaLcdBuffer = nullptr;
Widget* runningFS = nullptr;
LuaWidget *runningFS = nullptr;

static int8_t getTextHorizontalOffset(LcdFlags flags)
{
// no need to adjust if not right aligned
Expand Down Expand Up @@ -1413,7 +1414,7 @@ Exit full screen widget mode.
static int luaLcdExitFullScreen(lua_State *L)
{
if (runningFS) {
Widget* rfs = runningFS;
auto rfs = runningFS;
runningFS = nullptr;
rfs->setFullscreen(false);
}
Expand Down
1 change: 1 addition & 0 deletions radio/src/lua/api_colorlcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
#include "definitions.h"

EXTERN_C(LUALIB_API int luaopen_bitmap(lua_State * L));
EXTERN_C(LUALIB_API int luaopen_lvgl(lua_State * L));
Loading

0 comments on commit b4e33fc

Please sign in to comment.