From cb8a23cb5e1135c61f9ed57e8a9c63b1295ca027 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 10:08:45 +0200 Subject: [PATCH] Added confirmation dialog and use it to confirm shutdown on receiver still connected --- radio/src/gui/colorlcd/draw_functions.cpp | 46 ++++++-- radio/src/gui/colorlcd/fullscreen_dialog.cpp | 118 ++++++++++++++----- radio/src/gui/colorlcd/fullscreen_dialog.h | 5 +- radio/src/opentx.cpp | 20 +++- radio/src/opentx.h | 52 ++++---- 5 files changed, 177 insertions(+), 64 deletions(-) diff --git a/radio/src/gui/colorlcd/draw_functions.cpp b/radio/src/gui/colorlcd/draw_functions.cpp index fed04986b..65f07c39b 100644 --- a/radio/src/gui/colorlcd/draw_functions.cpp +++ b/radio/src/gui/colorlcd/draw_functions.cpp @@ -88,31 +88,54 @@ void drawSleepBitmap() lcdRefresh(); } +// +// TODO: move shutdown animation to Theme +// #define SHUTDOWN_CIRCLE_DIAMETER 150 void drawShutdownAnimation(uint32_t duration, uint32_t totalDuration, const char * message) { if (totalDuration == 0) return; - static const BitmapBuffer * shutdown = BitmapBuffer::loadBitmap(OpenTxTheme::instance()->getFilePath("shutdown.bmp")); + static const BitmapBuffer* shutdown = nullptr; + if (!shutdown) { + shutdown = BitmapBuffer::loadBitmap( + OpenTxTheme::instance()->getFilePath("shutdown.bmp")); + } lcd->reset(); if (shutdown) { OpenTxTheme::instance()->drawBackground(lcd); - lcd->drawBitmap((LCD_W - shutdown->width()) / 2, (LCD_H - shutdown->height()) / 2, shutdown); + lcd->drawBitmap((LCD_W - shutdown->width()) / 2, + (LCD_H - shutdown->height()) / 2, shutdown); int quarter = duration / (totalDuration / 5); - if (quarter >= 1) lcd->drawBitmapPattern(LCD_W/2, (LCD_H-SHUTDOWN_CIRCLE_DIAMETER)/2, LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, 0, SHUTDOWN_CIRCLE_DIAMETER/2); - if (quarter >= 2) lcd->drawBitmapPattern(LCD_W/2, LCD_H/2, LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, SHUTDOWN_CIRCLE_DIAMETER/2, SHUTDOWN_CIRCLE_DIAMETER/2); - if (quarter >= 3) lcd->drawBitmapPattern((LCD_W-SHUTDOWN_CIRCLE_DIAMETER)/2, LCD_H/2, LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, SHUTDOWN_CIRCLE_DIAMETER, SHUTDOWN_CIRCLE_DIAMETER/2); - if (quarter >= 4) lcd->drawBitmapPattern((LCD_W-SHUTDOWN_CIRCLE_DIAMETER)/2, (LCD_H-SHUTDOWN_CIRCLE_DIAMETER)/2, LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, SHUTDOWN_CIRCLE_DIAMETER*3/2, SHUTDOWN_CIRCLE_DIAMETER/2); - } - else { + if (quarter >= 1) + lcd->drawBitmapPattern(LCD_W / 2, (LCD_H - SHUTDOWN_CIRCLE_DIAMETER) / 2, + LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, 0, + SHUTDOWN_CIRCLE_DIAMETER / 2); + if (quarter >= 2) + lcd->drawBitmapPattern(LCD_W / 2, LCD_H / 2, LBM_SHUTDOWN_CIRCLE, + DEFAULT_COLOR, SHUTDOWN_CIRCLE_DIAMETER / 2, + SHUTDOWN_CIRCLE_DIAMETER / 2); + if (quarter >= 3) + lcd->drawBitmapPattern((LCD_W - SHUTDOWN_CIRCLE_DIAMETER) / 2, LCD_H / 2, + LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, + SHUTDOWN_CIRCLE_DIAMETER, + SHUTDOWN_CIRCLE_DIAMETER / 2); + if (quarter >= 4) + lcd->drawBitmapPattern((LCD_W - SHUTDOWN_CIRCLE_DIAMETER) / 2, + (LCD_H - SHUTDOWN_CIRCLE_DIAMETER) / 2, + LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, + SHUTDOWN_CIRCLE_DIAMETER * 3 / 2, + SHUTDOWN_CIRCLE_DIAMETER / 2); + } else { lcd->clear(); int quarter = duration / (totalDuration / 5); for (int i = 1; i <= 4; i++) { if (quarter >= i) { - lcd->drawSolidFilledRect(LCD_W / 2 - 70 + 24 * i, LCD_H / 2 - 10, 20, 20, DEFAULT_BGCOLOR); + lcd->drawSolidFilledRect(LCD_W / 2 - 70 + 24 * i, LCD_H / 2 - 10, 20, + 20, DEFAULT_BGCOLOR); } } } @@ -123,8 +146,9 @@ void drawShutdownAnimation(uint32_t duration, uint32_t totalDuration, const char void drawFatalErrorScreen(const char * message) { - lcd->clear(); - lcd->drawText(LCD_W/2, LCD_H/2-20, message, FONT(XL)|CENTERED|ALARM_COLOR); + lcd->reset(); + lcd->clear(COLOR2FLAGS(BLACK)); + lcd->drawText(LCD_W/2, LCD_H/2-20, message, FONT(XL)|CENTERED|COLOR2FLAGS(WHITE)); WDG_RESET(); lcdRefresh(); diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.cpp b/radio/src/gui/colorlcd/fullscreen_dialog.cpp index 3182a766d..4236c7523 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.cpp +++ b/radio/src/gui/colorlcd/fullscreen_dialog.cpp @@ -23,23 +23,23 @@ #include "opentx.h" #include "libopenui.h" -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), - type(type), - title(std::move(title)), - message(std::move(message)), - action(std::move(action)), - confirmHandler(confirmHandler) +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), + type(type), + title(std::move(title)), + message(std::move(message)), + action(std::move(action)), + confirmHandler(confirmHandler) { Layer::push(this); #if defined(HARDWARE_TOUCH) - new FabButton(this, LCD_W - 50, LCD_H - 50, ICON_NEXT, - [=]() -> uint8_t { - if (confirmHandler) - confirmHandler(); - return 0; - }); + new FabButton(this, LCD_W - 50, LCD_H - 50, ICON_NEXT, [=]() -> uint8_t { + if (confirmHandler) confirmHandler(); + return 0; + }); #endif bringToTop(); @@ -50,34 +50,58 @@ void FullScreenDialog::paint(BitmapBuffer * dc) { OpenTxTheme::instance()->drawBackground(dc); - dc->drawFilledRect(0, ALERT_FRAME_TOP, LCD_W, ALERT_FRAME_HEIGHT, SOLID, FOCUS_COLOR, OPACITY(8)); + dc->drawFilledRect(0, ALERT_FRAME_TOP, LCD_W, ALERT_FRAME_HEIGHT, SOLID, + FOCUS_COLOR, OPACITY(8)); - if (type == WARNING_TYPE_ALERT || type == WARNING_TYPE_ASTERISK) - dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->asterisk); - else if (type == WARNING_TYPE_INFO) - dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->busy); - else // confirmation - dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->question); + if (type == WARNING_TYPE_ALERT || type == WARNING_TYPE_ASTERISK) { + dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, + OpenTxTheme::instance()->asterisk); + } + else if (type == WARNING_TYPE_INFO) { + dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, + OpenTxTheme::instance()->busy); + } + else { // confirmation + dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, + OpenTxTheme::instance()->question); + } 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, ALARM_COLOR|FONT(XL)); - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, title.c_str(), ALARM_COLOR|FONT(XL)); +#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || \ + defined(TRANSLATIONS_CZ) + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, STR_WARNING, + ALARM_COLOR | FONT(XL)); + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, + title.c_str(), ALARM_COLOR | FONT(XL)); #else - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), ALARM_COLOR|FONT(XL)); - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, STR_WARNING, ALARM_COLOR|FONT(XL)); + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), + ALARM_COLOR | FONT(XL)); + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, + STR_WARNING, ALARM_COLOR | FONT(XL)); #endif - } - else if (!title.empty()) { - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), ALARM_COLOR|FONT(XL)); + } else if (!title.empty()) { + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), + ALARM_COLOR | FONT(XL)); } if (!message.empty()) { - dc->drawText(ALERT_MESSAGE_LEFT, ALERT_MESSAGE_TOP, message.c_str(), FONT(BOLD)); + 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)); + 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, 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); } } @@ -152,9 +176,41 @@ void FullScreenDialog::runForever() deleteLater(); } +void FullScreenDialog::runForeverNoPwrCheck() +{ + running = true; + + while (running) { + checkBacklight(); + WDG_RESET(); + + RTOS_WAIT_MS(1); + MainWindow::instance()->run(false); + } + + deleteLater(); +} + void raiseAlert(const char * title, const char * msg, const char * action, uint8_t sound) { AUDIO_ERROR_MESSAGE(sound); - auto dialog = new FullScreenDialog(WARNING_TYPE_ALERT, title ? title : "", msg ? msg : "", action ? action : ""); + auto dialog = new FullScreenDialog(WARNING_TYPE_ALERT, title ? title : "", + msg ? msg : "", action ? action : ""); dialog->runForever(); } + +// POPUP_CONFIRMATION +bool confirmationDialog(const char* title, const char* msg, bool checkPwr) +{ + bool confirmed = false; + auto dialog = new FullScreenDialog(WARNING_TYPE_CONFIRM, title ? title : "", + msg ? msg : "", "", + [&confirmed]() { confirmed = true; }); + if (checkPwr) { + dialog->runForever(); + } else { + dialog->runForeverNoPwrCheck(); + } + + return confirmed; +} diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.h b/radio/src/gui/colorlcd/fullscreen_dialog.h index aeb1b9140..c97fc81a7 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.h +++ b/radio/src/gui/colorlcd/fullscreen_dialog.h @@ -34,7 +34,9 @@ enum DialogType { class FullScreenDialog : public FormGroup { public: - FullScreenDialog(uint8_t type, std::string title, std::string message = "", std::string action = "", const std::function & confirmHandler = nullptr); + FullScreenDialog(uint8_t type, std::string title, std::string message = "", + std::string action = "", + const std::function& confirmHandler = nullptr); #if defined(DEBUG_WINDOWS) std::string getName() const override @@ -69,6 +71,7 @@ class FullScreenDialog : public FormGroup } void runForever(); + void runForeverNoPwrCheck(); protected: uint8_t type; diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 86becb0f8..7ec619735 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2058,9 +2058,12 @@ uint32_t pwrCheck() { #if !defined(COLORLCD) + lcdRefreshWait(); lcdClear(); + POPUP_CONFIRMATION(STR_MODEL_SHUTDOWN, nullptr); + #if defined(SHUTDOWN_CONFIRMATION) if (TELEMETRY_STREAMING() && !g_eeGeneral.disableRssiPoweroffAlarm) { SET_WARNING_INFO(STR_MODEL_STILL_POWERED, sizeof(TR_MODEL_STILL_POWERED), 0); @@ -2068,6 +2071,7 @@ uint32_t pwrCheck() #else SET_WARNING_INFO(STR_MODEL_STILL_POWERED, sizeof(TR_MODEL_STILL_POWERED), 0); #endif + event_t evt = getEvent(false); DISPLAY_WARNING(evt); LED_ERROR_BEGIN(); @@ -2085,8 +2089,22 @@ uint32_t pwrCheck() LED_ERROR_END(); return e_power_on; } -#endif +#else // COLORLCD + + // TODO: abort dialog condition (here, RSSI lost) + if (confirmationDialog(STR_MODEL_SHUTDOWN, STR_MODEL_STILL_POWERED, false)) { + pwr_check_state = PWR_CHECK_OFF; + return e_power_off; + } else { + // shutdown has been cancelled + pwr_check_state = PWR_CHECK_PAUSED; + LED_ERROR_END(); + return e_power_on; + } + +#endif // COLORLCD } + haptic.play(15, 3, PLAY_NOW); pwr_check_state = PWR_CHECK_OFF; return e_power_off; diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 3dcce843b..18c2c7bcb 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -460,29 +460,41 @@ uint16_t evalChkSum(); void alert(const char * title, const char * msg, uint8_t sound); #if !defined(GUI) + #define RAISE_ALERT(...) #define ALERT(...) -#elif defined(COLORLCD) - void raiseAlert(const char * title, const char * msg, const char * info, uint8_t sound); - inline void RAISE_ALERT(const char * title, const char * msg, const char * info, uint8_t sound) - { - raiseAlert(title, msg, info, sound); - } - inline void ALERT(const char * title, const char * msg, uint8_t sound) - { - raiseAlert(title, msg, "", sound); - } -#else - inline void RAISE_ALERT(const char * title, const char * msg, const char * info, uint8_t sound) - { - showAlertBox(title, msg, info, sound); - } - inline void ALERT(const char * title, const char * msg, uint8_t sound) - { - alert(title, msg, sound); - } -#endif +#elif defined(COLORLCD) + +bool confirmationDialog(const char *title, const char *msg, bool checkPwr = true); + +void raiseAlert(const char *title, const char *msg, const char *info, + uint8_t sound); + +inline void RAISE_ALERT(const char *title, const char *msg, const char *info, + uint8_t sound) +{ + raiseAlert(title, msg, info, sound); +} +inline void ALERT(const char *title, const char *msg, uint8_t sound) +{ + raiseAlert(title, msg, "", sound); +} + +#else // !COLORLCD && GUI + +inline void RAISE_ALERT(const char *title, const char *msg, const char *info, + uint8_t sound) +{ + showAlertBox(title, msg, info, sound); +} + +inline void ALERT(const char *title, const char *msg, uint8_t sound) +{ + alert(title, msg, sound); +} + +#endif // !COLORLCD && GUI enum PerOutMode { e_perout_mode_normal = 0,