From a013fccc7800ba6bc6c854eaa723893b10e1fed0 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 30 May 2022 18:27:30 +0200 Subject: [PATCH] fix: full screen dialogs --- radio/src/gui/colorlcd/LvglWrapper.cpp | 7 ++ radio/src/gui/colorlcd/LvglWrapper.h | 20 +++-- radio/src/gui/colorlcd/fullscreen_dialog.cpp | 86 ++++++++----------- radio/src/gui/colorlcd/fullscreen_dialog.h | 8 +- radio/src/gui/colorlcd/popups.cpp | 40 ++++----- radio/src/gui/colorlcd/switch_warn_dialog.cpp | 64 +++++++------- radio/src/gui/colorlcd/switch_warn_dialog.h | 34 +++----- radio/src/main.cpp | 22 ++--- 8 files changed, 128 insertions(+), 153 deletions(-) diff --git a/radio/src/gui/colorlcd/LvglWrapper.cpp b/radio/src/gui/colorlcd/LvglWrapper.cpp index 70a85241a..5c6f008a4 100644 --- a/radio/src/gui/colorlcd/LvglWrapper.cpp +++ b/radio/src/gui/colorlcd/LvglWrapper.cpp @@ -373,6 +373,13 @@ void LvglWrapper::run() lv_timer_handler(); } +void LvglWrapper::runNested() +{ + // Manual refresh + lv_refr_now(nullptr); + pollInputs(); +} + void LvglWrapper::pollInputs() { lv_indev_t* indev = nullptr; diff --git a/radio/src/gui/colorlcd/LvglWrapper.h b/radio/src/gui/colorlcd/LvglWrapper.h index 50621855e..8c845f03e 100644 --- a/radio/src/gui/colorlcd/LvglWrapper.h +++ b/radio/src/gui/colorlcd/LvglWrapper.h @@ -60,18 +60,24 @@ class LvglWidgetFactory class LvglWrapper { - public: - static LvglWrapper* instance(); + static LvglWrapper *_instance; + static void pollInputs(); - void run(); - void pollInputs(); + tmr10ms_t lastTick = 0; + // TODO: add driver instances here - private: LvglWrapper(); ~LvglWrapper() {} - static LvglWrapper *_instance; - tmr10ms_t lastTick = 0; + public: + static LvglWrapper* instance(); + + // Called from UI task: executes the LVGL timer handler + void run(); + + // Call it when running the loop manually from within + // the LVGL timer handler (blocking UI code) + static void runNested(); }; #endif // _LVGLWRAPPER_H_ diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.cpp b/radio/src/gui/colorlcd/fullscreen_dialog.cpp index 28995d406..051b5aa87 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.cpp +++ b/radio/src/gui/colorlcd/fullscreen_dialog.cpp @@ -28,7 +28,7 @@ FullScreenDialog::FullScreenDialog( uint8_t type, std::string title, std::string message, std::string action, const std::function& confirmHandler) : - FormGroup(MainWindow::instance(), {0, 0, LCD_W, LCD_H}, OPAQUE | FORM_NO_BORDER), + Window(MainWindow::instance(), {0, 0, LCD_W, LCD_H}, OPAQUE), type(type), title(std::move(title)), message(std::move(message)), @@ -36,22 +36,21 @@ FullScreenDialog::FullScreenDialog( confirmHandler(confirmHandler) { Layer::push(this); - - // TODO: if 'confirmHandler': - // -> add a confirm / cancel button - // -#if defined(HARDWARE_TOUCH) && 0 - new FabButton(this, LCD_W - (FAB_BUTTON_SIZE + PAGE_PADDING), - LCD_H - (FAB_BUTTON_SIZE + PAGE_PADDING), ICON_NEXT, - [=]() -> uint8_t { - deleteLater(); - if (confirmHandler) confirmHandler(); - return 0; - }); -#endif + +// // TODO: if 'confirmHandler': +// // -> add a confirm / cancel button +// // +// #if defined(HARDWARE_TOUCH) && 0 +// new FabButton(this, LCD_W - (FAB_BUTTON_SIZE + PAGE_PADDING), +// LCD_H - (FAB_BUTTON_SIZE + PAGE_PADDING), ICON_NEXT, +// [=]() -> uint8_t { +// deleteLater(); +// if (confirmHandler) confirmHandler(); +// return 0; +// }); +// #endif bringToTop(); - // setFocus(SET_FOCUS_DEFAULT); } void FullScreenDialog::paint(BitmapBuffer * dc) @@ -122,21 +121,6 @@ void FullScreenDialog::onCancel() deleteLater(); } -#if defined(HARDWARE_TOUCH) -bool FullScreenDialog::onTouchStart(coord_t x, coord_t y) -{ - Window::onTouchStart(x, y); - return true; -} - -bool FullScreenDialog::onTouchEnd(coord_t x, coord_t y) -{ - Window::onTouchEnd(x, y); - deleteLater(); - return true; -} -#endif - void FullScreenDialog::checkEvents() { Window::checkEvents(); @@ -156,6 +140,16 @@ void FullScreenDialog::deleteLater(bool detach, bool trash) } } +static void run_ui_manually() +{ + checkBacklight(); + WDG_RESET(); + + RTOS_WAIT_MS(10); + LvglWrapper::runNested(); + MainWindow::instance()->run(); +} + void FullScreenDialog::runForever() { running = true; @@ -179,13 +173,7 @@ void FullScreenDialog::runForever() RTOS_WAIT_MS(1); continue; } - - checkBacklight(); - WDG_RESET(); - - RTOS_WAIT_MS(1); - mainWin->run(false); - LvglWrapper::instance()->run(); + run_ui_manually(); } deleteLater(); @@ -201,13 +189,7 @@ void FullScreenDialog::runForeverNoPwrCheck() #endif while (running) { resetBacklightTimeout(); - - checkBacklight(); - WDG_RESET(); - - RTOS_WAIT_MS(1); - mainWin->run(false); - LvglWrapper::instance()->run(); + run_ui_manually(); } deleteLater(); @@ -225,22 +207,22 @@ void raiseAlert(const char * title, const char * msg, const char * action, uint8 } // POPUP_CONFIRMATION -bool confirmationDialog(const char* title, const char* msg, bool checkPwr, const std::function& closeCondition) +bool confirmationDialog(const char* title, const char* msg, bool checkPwr, + const std::function& closeCondition) { bool confirmed = false; auto dialog = new FullScreenDialog(WARNING_TYPE_CONFIRM, title ? title : "", msg ? msg : "", "", [&confirmed]() { confirmed = true; }); - if(closeCondition) - { - dialog->setCloseCondition([&confirmed,&closeCondition]() { - if(closeCondition()) - { - confirmed=true; + if (closeCondition) { + dialog->setCloseCondition([&confirmed, &closeCondition]() { + if (closeCondition()) { + confirmed = true; return true; } else { return false; - }}); + } + }); } if (checkPwr) { diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.h b/radio/src/gui/colorlcd/fullscreen_dialog.h index 95be53d6a..0b0acf55d 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.h +++ b/radio/src/gui/colorlcd/fullscreen_dialog.h @@ -32,7 +32,7 @@ enum DialogType { WARNING_TYPE_INFO }; -class FullScreenDialog : public FormGroup +class FullScreenDialog : public Window { public: FullScreenDialog(uint8_t type, std::string title, std::string message = "", @@ -54,15 +54,9 @@ class FullScreenDialog : public FormGroup void paint(BitmapBuffer * dc) override; - // void onEvent(event_t event) override; void onClicked() override; void onCancel() override; -#if defined(HARDWARE_TOUCH) - bool onTouchStart(coord_t x, coord_t y) override; - bool onTouchEnd(coord_t x, coord_t y) override; -#endif - void deleteLater(bool detach = true, bool trash = true) override; void checkEvents() override; diff --git a/radio/src/gui/colorlcd/popups.cpp b/radio/src/gui/colorlcd/popups.cpp index 4d6313b63..8671b62d4 100644 --- a/radio/src/gui/colorlcd/popups.cpp +++ b/radio/src/gui/colorlcd/popups.cpp @@ -22,37 +22,29 @@ #include "popups.h" #include "libopenui.h" -static MessageDialog * createPopupInformation(const char * message) +static void _run_popup_dialog(const char* title, const char* msg, + const char* info = nullptr) { - return new MessageDialog(MainWindow::instance(), "Message", message); -} - -static MessageDialog * createPopupWarning(const char * message) -{ - return new MessageDialog(MainWindow::instance(), "Warning", message); + bool running = true; + auto md = new MessageDialog(MainWindow::instance(), title, msg); + md->setCloseHandler([&]() { running = false; }); + if (info) { + md->setInfoText(std::string(info)); + } + while (running) { + WDG_RESET(); + MainWindow::instance()->run(); + LvglWrapper::runNested(); + RTOS_WAIT_MS(20); + } } void POPUP_INFORMATION(const char * message) { - auto popup = createPopupInformation(message); - while (popup->getParent()) { - WDG_RESET(); - lv_refr_now(nullptr); - LvglWrapper::instance()->pollInputs(); - RTOS_WAIT_MS(20); - } + _run_popup_dialog("Message", message); } void POPUP_WARNING(const char * message, const char * info) { - auto popup = createPopupWarning(message); - if (info) { - popup->setInfoText(std::string(info)); - } - while (popup->getParent()) { - WDG_RESET(); - lv_refr_now(nullptr); - LvglWrapper::instance()->pollInputs(); - RTOS_WAIT_MS(20); - } + _run_popup_dialog("Warning", message, info); } diff --git a/radio/src/gui/colorlcd/switch_warn_dialog.cpp b/radio/src/gui/colorlcd/switch_warn_dialog.cpp index 7fbc820e7..aa22cbc7c 100644 --- a/radio/src/gui/colorlcd/switch_warn_dialog.cpp +++ b/radio/src/gui/colorlcd/switch_warn_dialog.cpp @@ -22,6 +22,25 @@ #include "switch_warn_dialog.h" #include "switches.h" +SwitchWarnDialog::SwitchWarnDialog() : + FullScreenDialog(WARNING_TYPE_ALERT, STR_SWITCHWARN) +{ + last_bad_switches = 0xff; + bad_pots = 0; + last_bad_pots = 0x0; + setCloseCondition(std::bind(&SwitchWarnDialog::warningInactive, this)); + + warn_label = new StaticText(this, rect_t{}, "", 0, COLOR_THEME_PRIMARY1 | FONT(BOLD)); + + lv_obj_t* obj = warn_label->getLvObj(); + lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); + + warn_label->setLeft(ALERT_MESSAGE_LEFT); + warn_label->setWidth(LCD_W - ALERT_MESSAGE_LEFT - PAGE_PADDING); + warn_label->setTop(ALERT_MESSAGE_TOP); + warn_label->setHeight(LCD_H - ALERT_MESSAGE_TOP - PAGE_PADDING); +} + bool SwitchWarnDialog::warningInactive() { if (!isSwitchWarningRequired(bad_pots)) @@ -42,55 +61,42 @@ bool SwitchWarnDialog::warningInactive() void SwitchWarnDialog::paint(BitmapBuffer * dc) { - if (!running) - return; - + if (!running) return; FullScreenDialog::paint(dc); +} - coord_t x = ALERT_MESSAGE_LEFT; - coord_t y = ALERT_MESSAGE_TOP; +void SwitchWarnDialog::checkEvents() +{ + if (!running) return; + + FullScreenDialog::checkEvents(); + if (deleted()) return; + + std::string warn_txt; swarnstate_t states = g_model.switchWarningState; - for (int i = 0; i < NUM_SWITCHES; ++i) { if (SWITCH_WARNING_ALLOWED(i)) { swarnstate_t mask = ((swarnstate_t)0x07 << (i*3)); if (states & mask) { if ((switches_states & mask) != (states & mask)) { swarnstate_t state = (states >> (i*3)) & 0x07; - if (x < LCD_W) { - x = drawSwitch(dc, x, y, SWSRC_FIRST_SWITCH + i * 3 + state - 1, - COLOR_THEME_PRIMARY1 | FONT(BOLD)); - x += 5; - } - else { - dc->drawText(x, y, "...", COLOR_THEME_PRIMARY1 | FONT(BOLD)); - break; - } + warn_txt += getSwitchPositionName(SWSRC_FIRST_SWITCH + i * 3 + state - 1); } } } } if (g_model.potsWarnMode) { - x = ALERT_MESSAGE_LEFT; - y += 20; + if (!warn_txt.empty()) { warn_txt += '\n'; } for (int i = 0; i < NUM_POTS + NUM_SLIDERS; i++) { - if (!IS_POT_SLIDER_AVAILABLE(POT1 + i)) { - continue; - } + if (!IS_POT_SLIDER_AVAILABLE(POT1 + i)) { continue; } if ( (g_model.potsWarnEnabled & (1 << i))) { if (abs(g_model.potsWarnPosition[i] - GET_LOWRES_POT_POSITION(i)) > 1) { - if (y < LCD_H) { - char s[8]; - getStringAtIndex(s, STR_VSRCRAW, POT1 + i + 1); - dc->drawText(x, y, s, COLOR_THEME_PRIMARY1 | FONT(BOLD)); - x += 40; - } - else { - dc->drawText(x, y, "...", COLOR_THEME_PRIMARY1 | FONT(BOLD)); - } + warn_txt += STR_VSRCRAW[POT1 + i + 1]; } } } } + + warn_label->setText(warn_txt); } diff --git a/radio/src/gui/colorlcd/switch_warn_dialog.h b/radio/src/gui/colorlcd/switch_warn_dialog.h index 6318e501e..d14931be5 100644 --- a/radio/src/gui/colorlcd/switch_warn_dialog.h +++ b/radio/src/gui/colorlcd/switch_warn_dialog.h @@ -27,31 +27,25 @@ #include "opentx.h" #include "gridlayout.h" -class SwitchWarnDialog: public FullScreenDialog { - public: - SwitchWarnDialog(): - FullScreenDialog(WARNING_TYPE_ALERT, STR_SWITCHWARN) - { - last_bad_switches = 0xff; - bad_pots = 0; - last_bad_pots = 0x0; - setCloseCondition(std::bind(&SwitchWarnDialog::warningInactive, this)); - } +class SwitchWarnDialog : public FullScreenDialog +{ + public: + SwitchWarnDialog(); #if defined(DEBUG_WINDOWS) - std::string getName() const override - { - return "SwitchWarnDialog"; - } + std::string getName() const override { return "SwitchWarnDialog"; } #endif - void paint(BitmapBuffer * dc) override; + void checkEvents() override; + void paint(BitmapBuffer* dc) override; - protected: - swarnstate_t last_bad_switches; - uint16_t bad_pots; - uint16_t last_bad_pots; - bool warningInactive(); + protected: + swarnstate_t last_bad_switches; + uint16_t bad_pots; + uint16_t last_bad_pots; + StaticText* warn_label; + + bool warningInactive(); }; #endif diff --git a/radio/src/main.cpp b/radio/src/main.cpp index c9cf9a7d3..6bfacef24 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -364,16 +364,7 @@ void guiMain(event_t evt) } DEBUG_TIMER_START(debugTimerLua); - - // Run Lua scripts first that don't use LCD - luaTask( 0, false); - - // This is run from StandaloneLuaWindow::checkEvents() - // luaTask(evt, RUN_STNDAL_SCRIPT, true); - - // TODO: Telemetry scripts are run from Window::checkEvents() - // luaTask( 0, RUN_TELEM_BG_SCRIPT, false/* NO LCD */); - // luaTask(evt, RUN_TELEM_FG_SCRIPT, true/* LCD YES */); + luaTask(0, false); DEBUG_TIMER_STOP(debugTimerLua); t0 = get_tmr10ms() - t0; @@ -381,10 +372,13 @@ void guiMain(event_t evt) maxLuaDuration = t0; } #endif -#if defined(HARDWARE_TOUCH) - MainWindow* mainWin = MainWindow::instance(); - mainWin->setTouchEnabled(!isFunctionActive(FUNCTION_DISABLE_TOUCH) && isBacklightEnabled()); -#endif + + // TODO: use lv_indev_enable(touchDriver, true / false) instead + // #if defined(HARDWARE_TOUCH) + // MainWindow* mainWin = MainWindow::instance(); + // mainWin->setTouchEnabled(!isFunctionActive(FUNCTION_DISABLE_TOUCH) && + // isBacklightEnabled()); + // #endif LvglWrapper::instance()->run(); MainWindow::instance()->run();