From 475ad1fb6f2559c87013732cee0487269fffc865 Mon Sep 17 00:00:00 2001 From: philmoz Date: Wed, 25 Jan 2023 11:44:12 +1100 Subject: [PATCH] feat(ui): Improved Button/touch handling for throttle / switch alert screen (#3061) * Button and touch handling for throttle / switch alert screen. * Restore original touch behaviour for confirmation dialog. * Add buttons for 'actions' at bottom of screen. * Fix infinite loop that can happen in some instances. * Remove the option for a long press on the touch screen to close the dialog. On screen buttons must be used to close. Co-authored-by: Phil Mitchell --- radio/src/gui/colorlcd/fullscreen_dialog.cpp | 161 +++++++++--------- radio/src/gui/colorlcd/fullscreen_dialog.h | 13 +- radio/src/gui/colorlcd/switch_warn_dialog.cpp | 20 +-- radio/src/gui/colorlcd/switch_warn_dialog.h | 2 + 4 files changed, 103 insertions(+), 93 deletions(-) diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.cpp b/radio/src/gui/colorlcd/fullscreen_dialog.cpp index 23bff4b9904..1b163dbc9c0 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.cpp +++ b/radio/src/gui/colorlcd/fullscreen_dialog.cpp @@ -43,26 +43,70 @@ 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 bringToTop(); lv_obj_add_event_cb(lvobj, FullScreenDialog::long_pressed, LV_EVENT_LONG_PRESSED, nullptr); } +void FullScreenDialog::init() +{ + if (!loaded) { + loaded = true; + + std::string t; + if (type == WARNING_TYPE_ALERT) { +#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ) + t = STR_WARNING + "\n" + title; +#else + t = title + "\n" + STR_WARNING; +#endif + } else if (!title.empty()) { + t = title; + } + new StaticText(this, + rect_t{ALERT_TITLE_LEFT, ALERT_TITLE_TOP, LCD_W - ALERT_TITLE_LEFT - PAGE_PADDING, LCD_H - ALERT_TITLE_TOP - PAGE_PADDING}, + t.c_str(), 0, COLOR_THEME_WARNING | FONT(XL)); + + messageLabel = new StaticText(this, + rect_t{ALERT_MESSAGE_LEFT, ALERT_MESSAGE_TOP, LCD_W - ALERT_MESSAGE_LEFT - PAGE_PADDING, LCD_H - ALERT_MESSAGE_TOP - PAGE_PADDING}, + message.c_str(), 0, COLOR_THEME_PRIMARY1 | FONT(BOLD)); + + if (!action.empty()) { + auto btn = new TextButton(this, { (LCD_W - 280) / 2, LCD_H - 48, 280, 40 }, action.c_str(), + [=]() { + closeDialog(); + return 0; + }, COLOR_THEME_PRIMARY1 | FONT(BOLD)); + lv_obj_set_style_bg_color(btn->getLvObj(), makeLvColor(COLOR_THEME_SECONDARY3), 0); + lv_obj_set_style_bg_opa(btn->getLvObj(), LV_OPA_COVER, 0); + lv_obj_set_style_text_color(btn->getLvObj(), makeLvColor(COLOR_THEME_PRIMARY1), 0); + } else { + if (type == WARNING_TYPE_CONFIRM) { + auto btn = new TextButton(this, { LCD_W / 3 - 50, LCD_H - 48, 100, 40 }, STR_EXIT, + [=]() { + deleteLater(); + return 0; + }, COLOR_THEME_PRIMARY1 | FONT(BOLD)); + lv_obj_set_style_bg_color(btn->getLvObj(), makeLvColor(COLOR_THEME_SECONDARY3), 0); + lv_obj_set_style_bg_opa(btn->getLvObj(), LV_OPA_COVER, 0); + lv_obj_set_style_text_color(btn->getLvObj(), makeLvColor(COLOR_THEME_PRIMARY1), 0); + btn = new TextButton(this, { LCD_W * 2 / 3 - 50, LCD_H - 48, 100, 40 }, STR_OK, + [=]() { + closeDialog(); + return 0; + }, COLOR_THEME_PRIMARY1 | FONT(BOLD)); + lv_obj_set_style_bg_color(btn->getLvObj(), makeLvColor(COLOR_THEME_SECONDARY3), 0); + lv_obj_set_style_bg_opa(btn->getLvObj(), LV_OPA_COVER, 0); + lv_obj_set_style_text_color(btn->getLvObj(), makeLvColor(COLOR_THEME_PRIMARY1), 0); + } + } + } +} + void FullScreenDialog::paint(BitmapBuffer * dc) { + init(); + OpenTxTheme::instance()->drawBackground(dc); dc->drawFilledRect(0, ALERT_FRAME_TOP, LCD_W, ALERT_FRAME_HEIGHT, SOLID, @@ -78,44 +122,13 @@ void FullScreenDialog::paint(BitmapBuffer * dc) dc->drawMask(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->error, COLOR_THEME_WARNING); } +} - if (type == WARNING_TYPE_ALERT) { -#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || \ - defined(TRANSLATIONS_CZ) - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, STR_WARNING, - COLOR_THEME_WARNING | FONT(XL)); - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, - title.c_str(), COLOR_THEME_WARNING | FONT(XL)); -#else - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), - COLOR_THEME_WARNING | FONT(XL)); - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, - STR_WARNING, COLOR_THEME_WARNING | FONT(XL)); -#endif - } else if (!title.empty()) { - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), - COLOR_THEME_WARNING | FONT(XL)); - } - - if (!message.empty()) { - dc->drawText(ALERT_MESSAGE_LEFT, ALERT_MESSAGE_TOP, message.c_str(), - FONT(BOLD)); - } - - if (!action.empty()) { - dc->drawText(LCD_W / 2, ALERT_ACTION_TOP, action.c_str(), - CENTERED | FONT(BOLD)); - } else if (type == WARNING_TYPE_CONFIRM) { - - LcdFlags flags = FONT(BOLD); - int w = getTextWidth(STR_OK, 0, flags); - - dc->drawText(ALERT_MESSAGE_LEFT, ALERT_ACTION_TOP, - STR_OK, flags); - - dc->drawText(ALERT_MESSAGE_LEFT + w + 20, ALERT_ACTION_TOP, - STR_EXIT, flags); - } +void FullScreenDialog::closeDialog() +{ + if (confirmHandler) + confirmHandler(); + deleteLater(); } void FullScreenDialog::long_pressed(lv_event_t* e) @@ -124,15 +137,18 @@ void FullScreenDialog::long_pressed(lv_event_t* e) auto fs = (FullScreenDialog*)lv_obj_get_user_data(obj); if (fs) { - fs->onClicked(); + fs->closeDialog(); lv_indev_wait_release(lv_indev_get_act()); } } -void FullScreenDialog::onClicked() +void FullScreenDialog::onEvent(event_t event) { - if (confirmHandler) confirmHandler(); - deleteLater(); + // Buttons other than RTN or ENTER + if (type == WARNING_TYPE_ALERT) { + closeDialog(); + killEvents(event); + } } void FullScreenDialog::onCancel() @@ -169,7 +185,7 @@ static void run_ui_manually() MainWindow::instance()->run(false); } -void FullScreenDialog::runForever() +void FullScreenDialog::runForever(bool checkPwr) { running = true; @@ -180,29 +196,20 @@ void FullScreenDialog::runForever() while (running) { resetBacklightTimeout(); - auto check = pwrCheck(); - if (check == e_power_off) { - boardOff(); + if (checkPwr) { + auto check = pwrCheck(); + if (check == e_power_off) { + boardOff(); #if defined(SIMU) - return; + return; #endif + } else if (check == e_power_press) { + WDG_RESET(); + RTOS_WAIT_MS(1); + continue; + } } - else if (check == e_power_press) { - WDG_RESET(); - RTOS_WAIT_MS(1); - continue; - } - run_ui_manually(); - } - deleteLater(); -} - -void FullScreenDialog::runForeverNoPwrCheck() -{ - running = true; - while (running) { - resetBacklightTimeout(); run_ui_manually(); } @@ -239,11 +246,7 @@ bool confirmationDialog(const char* title, const char* msg, bool checkPwr, }); } - if (checkPwr) { - dialog->runForever(); - } else { - dialog->runForeverNoPwrCheck(); - } + dialog->runForever(checkPwr); return confirmed; } diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.h b/radio/src/gui/colorlcd/fullscreen_dialog.h index c992e55bae7..759d538230f 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.h +++ b/radio/src/gui/colorlcd/fullscreen_dialog.h @@ -32,6 +32,8 @@ enum DialogType { WARNING_TYPE_INFO }; +class StaticText; + class FullScreenDialog : public Window { public: @@ -54,7 +56,7 @@ class FullScreenDialog : public Window void paint(BitmapBuffer * dc) override; - void onClicked() override; + void onEvent(event_t event) override; void onCancel() override; void deleteLater(bool detach = true, bool trash = true) override; @@ -66,8 +68,9 @@ class FullScreenDialog : public Window closeCondition = std::move(handler); } - void runForever(); - void runForeverNoPwrCheck(); + void runForever(bool checkPwr = true); + + void closeDialog(); protected: uint8_t type; @@ -77,6 +80,10 @@ class FullScreenDialog : public Window bool running = false; std::function closeCondition; std::function confirmHandler; + bool loaded = false; + StaticText* messageLabel; + + virtual void init(); static void long_pressed(lv_event_t* e); }; diff --git a/radio/src/gui/colorlcd/switch_warn_dialog.cpp b/radio/src/gui/colorlcd/switch_warn_dialog.cpp index aa22cbc7ce3..c93db9b2bee 100644 --- a/radio/src/gui/colorlcd/switch_warn_dialog.cpp +++ b/radio/src/gui/colorlcd/switch_warn_dialog.cpp @@ -23,22 +23,20 @@ #include "switches.h" SwitchWarnDialog::SwitchWarnDialog() : - FullScreenDialog(WARNING_TYPE_ALERT, STR_SWITCHWARN) + FullScreenDialog(WARNING_TYPE_ALERT, STR_SWITCHWARN, "", STR_PRESS_ANY_KEY_TO_SKIP) { 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); +void SwitchWarnDialog::init() +{ + if (!loaded) { + FullScreenDialog::init(); + lv_label_set_long_mode(messageLabel->getLvObj(), LV_LABEL_LONG_DOT); + } } bool SwitchWarnDialog::warningInactive() @@ -98,5 +96,5 @@ void SwitchWarnDialog::checkEvents() } } - warn_label->setText(warn_txt); + messageLabel->setText(warn_txt); } diff --git a/radio/src/gui/colorlcd/switch_warn_dialog.h b/radio/src/gui/colorlcd/switch_warn_dialog.h index d14931be5ee..47a5c549b8f 100644 --- a/radio/src/gui/colorlcd/switch_warn_dialog.h +++ b/radio/src/gui/colorlcd/switch_warn_dialog.h @@ -46,6 +46,8 @@ class SwitchWarnDialog : public FullScreenDialog StaticText* warn_label; bool warningInactive(); + + void init() override; }; #endif