diff --git a/radio/src/gui/colorlcd/radio_sdmanager.cpp b/radio/src/gui/colorlcd/radio_sdmanager.cpp index 633b6be79..3e9227cb0 100644 --- a/radio/src/gui/colorlcd/radio_sdmanager.cpp +++ b/radio/src/gui/colorlcd/radio_sdmanager.cpp @@ -259,7 +259,7 @@ void RadioSdManagerPage::build(FormWindow * window) menu->addLine(STR_EXECUTE_FILE, [=]() { luaExec(getFullPath(name)); //TODO: check 'luaState' - new StandaloneLuaWindow(window); + StandaloneLuaWindow::instance()->attach(window); }); } #endif diff --git a/radio/src/gui/colorlcd/radio_tools.cpp b/radio/src/gui/colorlcd/radio_tools.cpp index bb08bcb84..d3be72812 100644 --- a/radio/src/gui/colorlcd/radio_tools.cpp +++ b/radio/src/gui/colorlcd/radio_tools.cpp @@ -121,7 +121,7 @@ void RadioToolsPage::rebuild(FormWindow * window) f_chdir("/SCRIPTS/TOOLS/"); luaExec(path_str.c_str()); // TODO: check 'luaState' - new StandaloneLuaWindow(window); + StandaloneLuaWindow::instance()->attach(window); return 0; }, 0); diff --git a/radio/src/gui/colorlcd/standalone_lua.cpp b/radio/src/gui/colorlcd/standalone_lua.cpp index bcdee8a8e..222dc319e 100644 --- a/radio/src/gui/colorlcd/standalone_lua.cpp +++ b/radio/src/gui/colorlcd/standalone_lua.cpp @@ -23,30 +23,81 @@ #include "lua/lua_api.h" constexpr uint32_t STANDALONE_LUA_REFRESH = 1000 / 5; // 5Hz +using std::string; + +void LuaPopup::paint(BitmapBuffer* dc, uint8_t type, const char* text, const char* info) +{ + // popup background + dc->drawSolidFilledRect(0, 0, rect.w, POPUP_HEADER_HEIGHT, + FOCUS_BGCOLOR); + + const char* title = text;//TODO: based on 'type' + + // title bar + dc->drawText(FIELD_PADDING_LEFT, + (POPUP_HEADER_HEIGHT - getFontHeight(FONT(STD))) / 2, + title, FOCUS_COLOR); + + dc->drawSolidFilledRect(0, POPUP_HEADER_HEIGHT, rect.w, + rect.h - POPUP_HEADER_HEIGHT, + DEFAULT_BGCOLOR); + + dc->drawText(FIELD_PADDING_LEFT, + POPUP_HEADER_HEIGHT + PAGE_LINE_HEIGHT, + info, DEFAULT_COLOR); +} + +// singleton instance +StandaloneLuaWindow* StandaloneLuaWindow::_instance; + +// LUA lcd buffer uint16_t* lcdGetBackupBuffer(); -StandaloneLuaWindow::StandaloneLuaWindow(Window* parent) : - Window(parent->getFullScreenWindow(), {0, 0, LCD_W, LCD_H}, OPAQUE), - lcdBuffer(BMP_RGB565, LCD_W, LCD_H, lcdGetBackupBuffer()) +StandaloneLuaWindow::StandaloneLuaWindow() : + Window(nullptr, {0, 0, LCD_W, LCD_H}, OPAQUE), + lcdBuffer(BMP_RGB565, LCD_W, LCD_H, lcdGetBackupBuffer()), + popup({50, 73, LCD_W - 100, LCD_H - 146}) { +} + +StandaloneLuaWindow* StandaloneLuaWindow::instance() +{ + if (!_instance) { + _instance = new StandaloneLuaWindow(); + } + + return _instance; +} + +void StandaloneLuaWindow::attach(Window* newParent) +{ + Window::attach(newParent->getFullScreenWindow()); Layer::push(this); setFocus(); } -void StandaloneLuaWindow::deleteLater(bool detach, bool trash) +void StandaloneLuaWindow::deleteLater(bool detach, bool /*trash*/) { Layer::pop(this); - Window::deleteLater(detach, trash); + + // do not trash: we are a singleton + if (static_cast(focusWindow) == static_cast(this)) { + focusWindow = nullptr; + } + + // detach from parent + if (detach) + this->detach(); + + if (closeHandler) { + closeHandler(); + } } void StandaloneLuaWindow::paint(BitmapBuffer* dc) { dc->drawSolidFilledRect(0, 0, width(), height(), DEFAULT_BGCOLOR); - - // TODO: - // -> grab coords from 'dc' - // -> copy from backup buffer into 'dc' dc->drawBitmap(0 - dc->getOffsetX(), 0 - dc->getOffsetY(), &lcdBuffer); } @@ -71,6 +122,32 @@ void StandaloneLuaWindow::onEvent(event_t evt) } #endif +bool StandaloneLuaWindow::displayPopup(event_t event, uint8_t type, const char* text, + const char* info, bool& result) +{ + // transparent background + lcdBuffer.drawFilledRect(0, 0, LCD_W, LCD_H, SOLID, + OVERLAY_COLOR, OPACITY(5)); + + // center pop-up + lcdBuffer.setOffset(LCD_W/2 - popup.rect.w/2, LCD_H/2 - popup.rect.h/2); + + // draw it, then clear the offset + popup.paint(&lcdBuffer, type, text, info); + lcdBuffer.clearOffset(); + + TRACE("displayPopup(event = 0x%x)", event); + if (event == EVT_KEY_BREAK(KEY_EXIT)) { + result = false; + return true; + } else if (event == EVT_KEY_BREAK(KEY_ENTER)) { + result = true; + return true; + } + + return false; +} + extern BitmapBuffer* luaLcdBuffer; void StandaloneLuaWindow::runLua(event_t evt) diff --git a/radio/src/gui/colorlcd/standalone_lua.h b/radio/src/gui/colorlcd/standalone_lua.h index 5a0eaacbd..a77e656e4 100644 --- a/radio/src/gui/colorlcd/standalone_lua.h +++ b/radio/src/gui/colorlcd/standalone_lua.h @@ -22,26 +22,46 @@ #include "libopenui.h" +struct LuaPopup +{ + rect_t rect; + LuaPopup(rect_t r) : rect(r) {} + void paint(BitmapBuffer* dc, uint8_t type, const char* text, const char* info); +}; + class StandaloneLuaWindow : public Window { - public: - explicit StandaloneLuaWindow(Window* parent); + static StandaloneLuaWindow* _instance; - void deleteLater(bool detach=true, bool trash=true) override; - void paint(BitmapBuffer* dc) override; - void checkEvents() override; + explicit StandaloneLuaWindow(); + +public: + static StandaloneLuaWindow* instance(); + + void attach(Window* newParent); + void deleteLater(bool detach = true, bool trash = true) override; + void paint(BitmapBuffer* dc) override; + void checkEvents() override; #if defined(DEBUG_WINDOWS) - std::string getName() const override { return "StandaloneLuaWindow"; } + std::string getName() const override { return "StandaloneLuaWindow"; } #endif #if defined(HARDWARE_KEYS) - void onEvent(event_t evt) override; + void onEvent(event_t evt) override; #endif - protected: - BitmapBuffer lcdBuffer; - uint32_t lastRefresh = 0; + bool displayPopup(event_t event, uint8_t type, const char* text, + const char* info, bool& result); - void runLua(event_t evt); +protected: + // GFX + BitmapBuffer lcdBuffer; + uint32_t lastRefresh = 0; + + // pop-ups + LuaPopup popup; + + // run LUA code + void runLua(event_t evt); }; diff --git a/radio/src/gui/colorlcd/theme.cpp b/radio/src/gui/colorlcd/theme.cpp index ba8bb6f30..5954ca760 100644 --- a/radio/src/gui/colorlcd/theme.cpp +++ b/radio/src/gui/colorlcd/theme.cpp @@ -112,14 +112,13 @@ void OpenTxTheme::drawBackground(BitmapBuffer * dc) const dc->drawSolidFilledRect(0, 0, LCD_W, LCD_H, DEFAULT_BGCOLOR); } -void OpenTxTheme::drawMessageBox(const char * title, const char * text, const char * action, uint32_t type) const -{ - -} +//void OpenTxTheme::drawMessageBox(const char *title, const char *text, +// const char *action, uint32_t type) const //{ // //if (flags & MESSAGEBOX_TYPE_ALERT) { // drawBackground(); -// lcdDrawFilledRect(0, POPUP_Y, LCD_W, POPUP_H, SOLID, FOCUS_COLOR | OPACITY(8)); +// lcdDrawFilledRect(0, POPUP_Y, LCD_W, POPUP_H, SOLID, FOCUS_COLOR | +// OPACITY(8)); // //} // // if (type == WARNING_TYPE_ALERT || type == WARNING_TYPE_ASTERISK) @@ -130,12 +129,15 @@ void OpenTxTheme::drawMessageBox(const char * title, const char * text, const ch // lcd->drawBitmap(POPUP_X-80, POPUP_Y+12, question); // // if (type == WARNING_TYPE_ALERT) { -//#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ) -// lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y, STR_WARNING, ALARM_COLOR|FONT(XL)); -// lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+28, title, ALARM_COLOR|FONT(XL)); +//#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || +//defined(TRANSLATIONS_CZ) +// lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y, STR_WARNING, +// ALARM_COLOR|FONT(XL)); lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+28, +// title, ALARM_COLOR|FONT(XL)); //#else // lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y, title, ALARM_COLOR|FONT(XL)); -// lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+28, STR_WARNING, ALARM_COLOR|FONT(XL)); +// lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+28, STR_WARNING, +// ALARM_COLOR|FONT(XL)); //#endif // } // else if (title) { diff --git a/radio/src/gui/colorlcd/theme.h b/radio/src/gui/colorlcd/theme.h index be31fbc52..90d2db9e8 100644 --- a/radio/src/gui/colorlcd/theme.h +++ b/radio/src/gui/colorlcd/theme.h @@ -89,8 +89,10 @@ class OpenTxTheme: public Theme virtual void drawMenuHeader(BitmapBuffer * dc, std::vector & tabs, uint8_t currentIndex) const = 0; - virtual void drawMessageBox(const char * title, const char * text, const char * action, uint32_t flags) const override; - // virtual void drawProgressBar(BitmapBuffer * dc, coord_t x, coord_t y, coord_t w, coord_t h, int value) const = 0; + // virtual void drawMessageBox(const char * title, const char * text, const + // char * action, uint32_t flags) const override; + // virtual void drawProgressBar(BitmapBuffer * dc, coord_t x, coord_t y, + // coord_t w, coord_t h, int value) const = 0; void drawCheckBox(BitmapBuffer * dc, bool checked, coord_t x, coord_t y, bool focus) const override; diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index e1981d297..34c59d499 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -29,6 +29,7 @@ #if defined(LIBOPENUI) #include "libopenui.h" #include "api_colorlcd.h" + #include "standalone_lua.h" #endif #if defined(PCBX12S) @@ -1159,6 +1160,7 @@ static int luaGetGlobalTimer(lua_State * L) return 1; } +#if defined(ENABLE_LUA_POPUP_INPUT) /*luadoc @function popupInput(title, event, input, min, max) @@ -1185,8 +1187,6 @@ Run function (key pressed) @status current Introduced in 2.0.0 */ - -/* TODO : fix, broken by popups rewrite static int luaPopupInput(lua_State * L) { event_t event = luaL_checkinteger(L, 2); @@ -1195,7 +1195,9 @@ static int luaPopupInput(lua_State * L) warningInputValueMax = luaL_checkinteger(L, 5); warningText = luaL_checkstring(L, 1); warningType = WARNING_TYPE_INPUT; + runPopupWarning(event); + if (warningResult) { warningResult = 0; lua_pushstring(L, "OK"); @@ -1209,7 +1211,7 @@ static int luaPopupInput(lua_State * L) warningText = NULL; return 1; } -*/ +#endif /*luadoc @function popupWarning(title, event) @@ -1227,13 +1229,27 @@ Run function (key pressed) @status current Introduced in 2.2.0 */ -#if 0 static int luaPopupWarning(lua_State * L) { +#if defined(COLORLCD) + const char* warningText = nullptr; + uint8_t warningType = 0; + bool warningResult = false; +#endif + event_t event = luaL_checkinteger(L, 2); warningText = luaL_checkstring(L, 1); warningType = WARNING_TYPE_ASTERISK; + +#if defined(COLORLCD) + if (StandaloneLuaWindow::instance()->displayPopup(event, warningType, warningText, + nullptr, warningResult)) { + warningText = nullptr; + } +#else runPopupWarning(event); +#endif + if (!warningText) { lua_pushstring(L, "CANCEL"); } @@ -1243,7 +1259,6 @@ static int luaPopupWarning(lua_State * L) } return 1; } -#endif /*luadoc @function popupConfirmation(title, event) deprecated, please replace by @@ -1264,9 +1279,16 @@ Run function (key pressed) @status current Introduced in 2.2.0, changed to (title, message, event) in 2.3.8 */ -#if 0 static int luaPopupConfirmation(lua_State * L) { +#if defined(COLORLCD) + // necessary to run the LUA pop-ups + uint8_t warningType = 0; + bool warningResult = false; + const char* warningText = nullptr; + const char* warningInfoText = nullptr; +#endif + warningType = WARNING_TYPE_CONFIRM; event_t event; @@ -1281,17 +1303,25 @@ static int luaPopupConfirmation(lua_State * L) event = luaL_optinteger(L, 3, 0); } +#if defined(COLORLCD) + if (StandaloneLuaWindow::instance()->displayPopup(event, warningType, warningText, + warningInfoText, warningResult)) { + warningText = nullptr; + } +#else runPopupWarning(event); +#endif + if (!warningText) { lua_pushstring(L, warningResult ? "OK" : "CANCEL"); } else { - warningText = NULL; + warningText = nullptr; lua_pushnil(L); } + return 1; } -#endif /*luadoc @function defaultStick(channel) @@ -1771,9 +1801,11 @@ const luaL_Reg opentxLib[] = { { "playDuration", luaPlayDuration }, { "playTone", luaPlayTone }, { "playHaptic", luaPlayHaptic }, - // { "popupInput", luaPopupInput }, - // { "popupWarning", luaPopupWarning }, - // { "popupConfirmation", luaPopupConfirmation }, +#if defined(ENABLE_LUA_POPUP_INPUT) + { "popupInput", luaPopupInput }, +#endif + { "popupWarning", luaPopupWarning }, + { "popupConfirmation", luaPopupConfirmation }, { "defaultStick", luaDefaultStick }, { "defaultChannel", luaDefaultChannel }, { "getRSSI", luaGetRSSI }, diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index b3fc0546e..553b32fea 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -748,8 +748,11 @@ void displayLuaError(const char * title) { #if !defined(COLORLCD) drawMessageBox(title); +#endif + if (lua_warning_info[0]) { char *split = strstr(lua_warning_info, ": "); +#if !defined(COLORLCD) if (split) { #if LCD_W == 128 if (strlen(split + 2) <= 20) { @@ -776,10 +779,12 @@ void displayLuaError(const char * title) // TODO lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y + FH + 3, // lua_warning_info, 40, SMLSIZE); } - } #else - POPUP_WARNING(title, lua_warning_info); + // Split line... + //if (split) { *(split+1) = '\n'; } + POPUP_WARNING(title, lua_warning_info); #endif + } } #if !defined(COLORLCD) diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 0b995317a..77b0e421f 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 0b995317a5f8fa2c62c9d693418141d1649619e5 +Subproject commit 77b0e421fc5790e777930aef1f7224155916629c