From 86d4f65f74bd5ba32ab1eac1faa5bf9387a15a6a Mon Sep 17 00:00:00 2001 From: philmoz Date: Fri, 17 Nov 2023 13:44:22 +1100 Subject: [PATCH] feat(color): Main navigation menu styling (#4320) --- .../480x272/button/alpha_button_on.png | Bin 5370 -> 0 bytes radio/src/gui/colorlcd/CMakeLists.txt | 1 - radio/src/gui/colorlcd/fab_button.cpp | 65 ------- radio/src/gui/colorlcd/fab_button.h | 52 ------ radio/src/gui/colorlcd/libopenui.h | 1 - radio/src/gui/colorlcd/select_fab_button.cpp | 41 +++-- radio/src/gui/colorlcd/select_fab_button.h | 27 +-- .../src/gui/colorlcd/select_fab_carousel.cpp | 10 +- radio/src/gui/colorlcd/select_fab_carousel.h | 19 +-- .../src/gui/colorlcd/themes/etx_lv_theme.cpp | 70 ++++++++ radio/src/gui/colorlcd/view_main_menu.cpp | 158 ++++++++---------- radio/src/gui/colorlcd/view_main_menu.h | 2 - .../libopenui/src/widgets/etx_obj_create.h | 2 + 13 files changed, 195 insertions(+), 253 deletions(-) delete mode 100644 radio/src/bitmaps/480x272/button/alpha_button_on.png delete mode 100644 radio/src/gui/colorlcd/fab_button.cpp delete mode 100644 radio/src/gui/colorlcd/fab_button.h diff --git a/radio/src/bitmaps/480x272/button/alpha_button_on.png b/radio/src/bitmaps/480x272/button/alpha_button_on.png deleted file mode 100644 index 9bd2cf5cf51840cc2e67e216c58918fa6c4bd2bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5370 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%0Dy!5 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 pressHandler, - WindowFlags windowFlags) : - Button(parent, - {x, y, FAB_BUTTON_SIZE, FAB_BUTTON_SIZE}, - pressHandler, windowFlags), - icon(icon) -{ -} - -FabButton::FabButton(FormWindow* parent, uint8_t icon, - std::function pressHandler, - WindowFlags windowFlags) : - Button(parent, {}, pressHandler, windowFlags), icon(icon) -{ -} - -void FabButton::paint(BitmapBuffer * dc) -{ - const BitmapBuffer* bitmap = checked() ? &ALPHA_BUTTON_ON : &ALPHA_BUTTON_OFF; - - dc->drawBitmap((width() - bitmap->width()) / 2, - (FAB_BUTTON_SIZE - bitmap->height()) / 2, bitmap); - - const BitmapBuffer* mask = EdgeTxTheme::instance()->getIconMask(icon); - if (mask) { - dc->drawMask((width() - mask->width()) / 2, - (FAB_BUTTON_SIZE - mask->height()) / 2, mask, COLOR2FLAGS(WHITE)); - } -} diff --git a/radio/src/gui/colorlcd/fab_button.h b/radio/src/gui/colorlcd/fab_button.h deleted file mode 100644 index 5073bb240..000000000 --- a/radio/src/gui/colorlcd/fab_button.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) EdgeTX - * - * Based on code named - * opentx - https://github.com/opentx/opentx - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _FAB_ICON_BUTTON_H_ -#define _FAB_ICON_BUTTON_H_ - -#include "button.h" - -constexpr coord_t FAB_BUTTON_SIZE = 68; - -class FabButton: public Button { - public: - FabButton(FormWindow * parent, coord_t x, coord_t y, - uint8_t icon, std::function pressHandler, - WindowFlags windowFlags = 0); - - FabButton(FormWindow * parent, uint8_t icon, - std::function pressHandler, - WindowFlags windowFlags = 0); - -#if defined(DEBUG_WINDOWS) - std::string getName() const override - { - return "FabButton"; - } -#endif - - void paint(BitmapBuffer * dc) override; - - protected: - uint8_t icon; -}; - -#endif diff --git a/radio/src/gui/colorlcd/libopenui.h b/radio/src/gui/colorlcd/libopenui.h index 546c4a6c0..563c71276 100644 --- a/radio/src/gui/colorlcd/libopenui.h +++ b/radio/src/gui/colorlcd/libopenui.h @@ -29,7 +29,6 @@ #include "mainwindow.h" #include "static.h" #include "button.h" -#include "fab_button.h" #include "toggleswitch.h" #include "numberedit.h" #include "timeedit.h" diff --git a/radio/src/gui/colorlcd/select_fab_button.cpp b/radio/src/gui/colorlcd/select_fab_button.cpp index 832ff2896..44e087c7c 100644 --- a/radio/src/gui/colorlcd/select_fab_button.cpp +++ b/radio/src/gui/colorlcd/select_fab_button.cpp @@ -21,31 +21,40 @@ #include "select_fab_button.h" -SelectFabButton::SelectFabButton(FormWindow* parent, - uint8_t icon, const char* title, +#include "font.h" +#include "static.h" +#include "theme.h" + +const uint8_t __alpha_button_off[]{ +#include "alpha_button_off.lbm" +}; +LZ4Bitmap ALPHA_BUTTON_OFF(BMP_ARGB4444, __alpha_button_off); + +SelectFabButton::SelectFabButton(FormWindow* parent, uint8_t icon, + const char* title, std::function pressHandler, WindowFlags windowFlags) : - // FabButton uses center coordinates, we want top left corner: - FabButton(parent, icon, pressHandler, windowFlags), + Button(parent, {}, pressHandler, windowFlags, 0, etx_quick_button_create), + icon(icon), title(title) { - // Add some space on either side on the button - setWidth(FAB_BUTTON_SIZE + SELECT_BUTTON_BORDER); - - // 2 Lines extra for the text + half border - setHeight(FAB_BUTTON_SIZE + 2 * PAGE_LINE_HEIGHT + SELECT_BUTTON_BORDER / 2); + padAll(0); + new StaticText(this, {1, FAB_BUTTON_SIZE - 14, FAB_BUTTON_SIZE - 4, 0}, title, 0, + COLOR2FLAGS(WHITE) | CENTERED); } void SelectFabButton::paint(BitmapBuffer* dc) { - FabButton::paint(dc); + const BitmapBuffer* bitmap = &ALPHA_BUTTON_OFF; - dc->drawSizedText(width() / 2, FAB_BUTTON_SIZE, - title.c_str(), title.size(), - COLOR2FLAGS(WHITE) | CENTERED); + dc->drawBitmap((FAB_BUTTON_SIZE - bitmap->width()) / 2, + (FAB_BUTTON_SIZE - bitmap->height()) / 2 - 6, bitmap); - if (hasFocus()) { - dc->drawSolidRect(0, 0, width(), height(), 2, COLOR2FLAGS(WHITE)); + const BitmapBuffer* mask = EdgeTxTheme::instance()->getIconMask(icon); + if (mask) { + dc->drawMask((FAB_BUTTON_SIZE - mask->width()) / 2, + (FAB_BUTTON_SIZE - mask->height()) / 2 - 6, mask, + COLOR2FLAGS(WHITE)); } } @@ -59,5 +68,5 @@ void SelectFabButton::onEvent(event_t event) return; } #endif - FabButton::onEvent(event); + Button::onEvent(event); } diff --git a/radio/src/gui/colorlcd/select_fab_button.h b/radio/src/gui/colorlcd/select_fab_button.h index c190f4920..7cc85b19f 100644 --- a/radio/src/gui/colorlcd/select_fab_button.h +++ b/radio/src/gui/colorlcd/select_fab_button.h @@ -21,20 +21,25 @@ #pragma once -#include "fab_button.h" +#include "button.h" -constexpr coord_t SELECT_BUTTON_BORDER = 12; +constexpr coord_t FAB_BUTTON_SIZE = 80; -class SelectFabButton : public FabButton +class SelectFabButton : public Button { - public: - SelectFabButton(FormWindow* parent, uint8_t icon, const char* title, - std::function pressHandler, - WindowFlags windowFlags = 0); + public: + SelectFabButton(FormWindow* parent, uint8_t icon, const char* title, + std::function pressHandler, + WindowFlags windowFlags = 0); - void paint(BitmapBuffer* dc) override; - void onEvent(event_t event) override; +#if defined(DEBUG_WINDOWS) + std::string getName() const override { return "SelectFabButton"; } +#endif - protected: - std::string title; + void paint(BitmapBuffer* dc) override; + void onEvent(event_t event) override; + + protected: + uint8_t icon; + std::string title; }; diff --git a/radio/src/gui/colorlcd/select_fab_carousel.cpp b/radio/src/gui/colorlcd/select_fab_carousel.cpp index 9f0bc3761..a3cecffcc 100644 --- a/radio/src/gui/colorlcd/select_fab_carousel.cpp +++ b/radio/src/gui/colorlcd/select_fab_carousel.cpp @@ -21,16 +21,10 @@ #include "select_fab_carousel.h" -SelectFabCarousel::SelectFabCarousel(Window* parent) : - FormWindow(parent, {}) +SelectFabCarousel::SelectFabCarousel(Window* parent) : FormWindow(parent, {}) { + padAll(0); setFlexLayout(LV_FLEX_FLOW_ROW_WRAP); - - coord_t w = parent->width() * 0.8; - w -= w % (FAB_BUTTON_SIZE + SELECT_BUTTON_BORDER); - lv_obj_set_width(lvobj, w); - - lv_obj_set_style_max_height(lvobj, lv_pct(85), 0); } void SelectFabCarousel::addButton(uint8_t icon, const char* title, diff --git a/radio/src/gui/colorlcd/select_fab_carousel.h b/radio/src/gui/colorlcd/select_fab_carousel.h index f8741ca3c..ca74ddc35 100644 --- a/radio/src/gui/colorlcd/select_fab_carousel.h +++ b/radio/src/gui/colorlcd/select_fab_carousel.h @@ -25,17 +25,14 @@ class SelectFabCarousel : public FormWindow { -public: - explicit SelectFabCarousel(Window* parent); + public: + explicit SelectFabCarousel(Window* parent); - // Maximum visible buttons (-> width of the carousel) - void setMaxButtons(uint8_t max); +#if defined(DEBUG_WINDOWS) + std::string getName() const override { return "SelectFabCarousel"; } +#endif - // Add a new button to the carousel - void addButton(uint8_t icon, const char* title, - std::function pressHandler); - -protected: - uint8_t maxButtons = 0; - uint8_t buttons = 0; + // Add a new button to the carousel + void addButton(uint8_t icon, const char* title, + std::function pressHandler); }; diff --git a/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp b/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp index 5f70469e4..dc27ac663 100644 --- a/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp +++ b/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp @@ -68,6 +68,7 @@ LV_STYLE_CONST_SINGLE_INIT(bg_opacity_transparent, LV_STYLE_BG_OPA, LV_OPA_TRANSP); LV_STYLE_CONST_SINGLE_INIT(bg_opacity_20, LV_STYLE_BG_OPA, LV_OPA_20); LV_STYLE_CONST_SINGLE_INIT(bg_opacity_50, LV_STYLE_BG_OPA, LV_OPA_50); +LV_STYLE_CONST_SINGLE_INIT(bg_opacity_75, LV_STYLE_BG_OPA, 187); LV_STYLE_CONST_SINGLE_INIT(bg_opacity_cover, LV_STYLE_BG_OPA, LV_OPA_COVER); LV_STYLE_CONST_SINGLE_INIT(fg_opacity_transparent, LV_STYLE_OPA, LV_OPA_TRANSP); LV_STYLE_CONST_SINGLE_INIT(fg_opacity_cover, LV_STYLE_OPA, LV_OPA_COVER); @@ -140,6 +141,14 @@ const lv_style_const_prop_t border_props[] = { }; LV_STYLE_CONST_MULTI_INIT(border, border_props); +// Border +const lv_style_const_prop_t border_transparent_props[] = { + LV_STYLE_CONST_BORDER_OPA(LV_OPA_TRANSP), + LV_STYLE_CONST_BORDER_WIDTH(BORDER_WIDTH), + LV_STYLE_PROP_INV, +}; +LV_STYLE_CONST_MULTI_INIT(border_transparent, border_transparent_props); + // Button const lv_style_const_prop_t btn_props[] = { LV_STYLE_CONST_PAD_TOP(PAD_SMALL), @@ -274,11 +283,13 @@ class EdgeTxStyles lv_style_t border_color_secondary1; lv_style_t border_color_secondary2; lv_style_t border_color_black; + lv_style_t border_color_white; lv_style_t border_color_focus; lv_style_t bg_color_grey; lv_style_t bg_color_white; lv_style_t bg_color_black; lv_style_t fg_color_black; + lv_style_t fg_color_white; // Fonts lv_style_t font_std; @@ -308,8 +319,12 @@ class EdgeTxStyles lv_style_set_bg_color(&bg_color_black, lv_color_black()); lv_style_init(&fg_color_black); lv_style_set_text_color(&fg_color_black, lv_color_black()); + lv_style_init(&fg_color_white); + lv_style_set_text_color(&fg_color_white, lv_color_white()); lv_style_init(&border_color_black); lv_style_set_border_color(&border_color_black, lv_color_black()); + lv_style_init(&border_color_white); + lv_style_set_border_color(&border_color_white, lv_color_white()); // Fonts lv_style_init(&font_std); @@ -636,6 +651,18 @@ void etx_button_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) LV_PART_MAIN | LV_STATE_DISABLED); } +void etx_quick_button_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) +{ + lv_obj_add_style(obj, (lv_style_t*)&border_transparent, LV_PART_MAIN); + lv_obj_add_style(obj, (lv_style_t*)&rounded, LV_PART_MAIN); + lv_obj_add_style(obj, &styles->fg_color_white, LV_PART_MAIN); + lv_obj_add_style(obj, (lv_style_t*)&btn, LV_PART_MAIN); + + lv_obj_add_style(obj, (lv_style_t*)&border, LV_PART_MAIN | LV_STATE_FOCUSED); + lv_obj_add_style(obj, &styles->border_color_white, + LV_PART_MAIN | LV_STATE_FOCUSED); +} + void etx_choice_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) { etx_add_border_rounded(obj); @@ -699,6 +726,14 @@ void modal_window_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) lv_obj_add_style(obj, &styles->bg_color_black, LV_PART_MAIN); } +void modal_dialog_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) +{ + window_base_constructor(class_p, obj); + lv_obj_add_style(obj, (lv_style_t*)&rounded, LV_PART_MAIN); + lv_obj_add_style(obj, (lv_style_t*)&bg_opacity_75, LV_PART_MAIN); + lv_obj_add_style(obj, &styles->bg_color_black, LV_PART_MAIN); +} + void modal_content_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) { window_base_constructor(class_p, obj); @@ -868,6 +903,19 @@ const lv_obj_class_t etx_button_class = { .instance_size = sizeof(lv_btn_t), }; +const lv_obj_class_t etx_quick_button_class = { + .base_class = &lv_btn_class, + .constructor_cb = etx_quick_button_constructor, + .destructor_cb = nullptr, + .user_data = nullptr, + .event_cb = nullptr, + .width_def = 80, + .height_def = 114, + .editable = LV_OBJ_CLASS_EDITABLE_INHERIT, + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .instance_size = sizeof(lv_btn_t), +}; + const lv_obj_class_t etx_menu_button_class = { .base_class = &lv_btn_class, .constructor_cb = etx_button_constructor, @@ -944,6 +992,18 @@ const lv_obj_class_t etx_modal_window_class = { .group_def = LV_OBJ_CLASS_EDITABLE_INHERIT, .instance_size = sizeof(lv_obj_t)}; +const lv_obj_class_t etx_modal_dialog_class = { + .base_class = &window_base_class, + .constructor_cb = modal_dialog_constructor, + .destructor_cb = nullptr, + .user_data = nullptr, + .event_cb = nullptr, + .width_def = 0, + .height_def = 0, + .editable = LV_OBJ_CLASS_EDITABLE_INHERIT, + .group_def = LV_OBJ_CLASS_EDITABLE_INHERIT, + .instance_size = sizeof(lv_obj_t)}; + const lv_obj_class_t etx_modal_content_class = { .base_class = &window_base_class, .constructor_cb = modal_content_constructor, @@ -1073,6 +1133,11 @@ lv_obj_t* etx_button_create(lv_obj_t* parent) return etx_create(&etx_button_class, parent); } +lv_obj_t* etx_quick_button_create(lv_obj_t* parent) +{ + return etx_create(&etx_quick_button_class, parent); +} + lv_obj_t* etx_menu_button_create(lv_obj_t* parent) { return etx_create(&etx_menu_button_class, parent); @@ -1103,6 +1168,11 @@ lv_obj_t* etx_modal_create(lv_obj_t* parent) return etx_create(&etx_modal_window_class, parent); } +lv_obj_t* etx_modal_dialog_create(lv_obj_t* parent) +{ + return etx_create(&etx_modal_dialog_class, parent); +} + lv_obj_t* etx_modal_content_create(lv_obj_t* parent) { return etx_create(&etx_modal_content_class, parent); diff --git a/radio/src/gui/colorlcd/view_main_menu.cpp b/radio/src/gui/colorlcd/view_main_menu.cpp index d36fda303..a47324910 100644 --- a/radio/src/gui/colorlcd/view_main_menu.cpp +++ b/radio/src/gui/colorlcd/view_main_menu.cpp @@ -20,80 +20,92 @@ */ #include "view_main_menu.h" -#include "menu.h" -#include "audio.h" -#include "translations.h" -#include "model_select.h" + #include "menu_model.h" #include "menu_radio.h" #include "menu_screen.h" +#include "model_select.h" +#include "select_fab_carousel.h" #include "view_about.h" #include "view_channels.h" #include "view_statistics.h" -#include "select_fab_carousel.h" #include "view_text.h" +#if LCD_W > LCD_H +#define VM_W (FAB_BUTTON_SIZE * 4 + 16) +#define VM_H ((FAB_BUTTON_SIZE + 34) * 2 + 16) +#else +#define VM_W (FAB_BUTTON_SIZE * 3 + 16) +#define VM_H ((FAB_BUTTON_SIZE + 34) * 3 + 16) +#endif + ViewMainMenu::ViewMainMenu(Window* parent, std::function closeHandler) : - Window(parent->getFullScreenWindow(), rect_t{}) + Window(parent->getFullScreenWindow(), + {(LCD_W - VM_W) / 2, (LCD_H - VM_H) / 2, VM_W, VM_H}, 0, 0, + etx_modal_dialog_create), + closeHandler(std::move(closeHandler)) { - this->closeHandler = std::move(closeHandler); + padAll(8); // Save focus Layer::push(this); - // Take over the screen - setWidth(parent->width()); - setHeight(parent->height()); - auto carousel = new SelectFabCarousel(this); - carousel->addButton(ICON_MODEL_SELECT,STR_MAIN_MENU_MANAGE_MODELS, [=]() -> uint8_t { - deleteLater(); - new ModelLabelsWindow(); - return 0; - }); + carousel->addButton(ICON_MODEL_SELECT, STR_MAIN_MENU_MANAGE_MODELS, + [=]() -> uint8_t { + deleteLater(); + new ModelLabelsWindow(); + return 0; + }); if (modelHasNotes()) { - carousel->addButton(ICON_MODEL_NOTES, STR_MAIN_MENU_MODEL_NOTES, [=]() -> uint8_t { - deleteLater(); - readModelNotes(true); - return 0; - }); + carousel->addButton(ICON_MODEL_NOTES, STR_MAIN_MENU_MODEL_NOTES, + [=]() -> uint8_t { + deleteLater(); + readModelNotes(true); + return 0; + }); } - carousel->addButton(ICON_MONITOR, STR_MAIN_MENU_CHANNEL_MONITOR, [=]() -> uint8_t { - deleteLater(); - new ChannelsViewMenu(); - return 0; - }); + carousel->addButton(ICON_MONITOR, STR_MAIN_MENU_CHANNEL_MONITOR, + [=]() -> uint8_t { + deleteLater(); + new ChannelsViewMenu(); + return 0; + }); - carousel->addButton(ICON_MODEL, STR_MAIN_MENU_MODEL_SETTINGS, [=]() -> uint8_t { - deleteLater(); - new ModelMenu(); - return 0; - }); + carousel->addButton(ICON_MODEL, STR_MAIN_MENU_MODEL_SETTINGS, + [=]() -> uint8_t { + deleteLater(); + new ModelMenu(); + return 0; + }); - carousel->addButton(ICON_RADIO, STR_MAIN_MENU_RADIO_SETTINGS, [=]() -> uint8_t { - deleteLater(); - new RadioMenu(); - return 0; - }); + carousel->addButton(ICON_RADIO, STR_MAIN_MENU_RADIO_SETTINGS, + [=]() -> uint8_t { + deleteLater(); + new RadioMenu(); + return 0; + }); - carousel->addButton(ICON_THEME, STR_MAIN_MENU_SCREEN_SETTINGS, [=]() -> uint8_t { - deleteLater(); - new ScreenMenu(); - return 0; - }); + carousel->addButton(ICON_THEME, STR_MAIN_MENU_SCREEN_SETTINGS, + [=]() -> uint8_t { + deleteLater(); + new ScreenMenu(); + return 0; + }); - carousel->addButton(ICON_MODEL_TELEMETRY, STR_MAIN_MENU_RESET_TELEMETRY, [=]() -> uint8_t { - deleteLater(); - Menu* resetMenu = new Menu(parent); - resetMenu->addLine(STR_RESET_FLIGHT, []() { flightReset(); }); - resetMenu->addLine(STR_RESET_TIMER1, []() { timerReset(0); }); - resetMenu->addLine(STR_RESET_TIMER2, []() { timerReset(1); }); - resetMenu->addLine(STR_RESET_TIMER3, []() { timerReset(2); }); - resetMenu->addLine(STR_RESET_TELEMETRY, []() { telemetryReset(); }); - return 0; - }); + carousel->addButton( + ICON_MODEL_TELEMETRY, STR_MAIN_MENU_RESET_TELEMETRY, [=]() -> uint8_t { + deleteLater(); + Menu* resetMenu = new Menu(parent); + resetMenu->addLine(STR_RESET_FLIGHT, []() { flightReset(); }); + resetMenu->addLine(STR_RESET_TIMER1, []() { timerReset(0); }); + resetMenu->addLine(STR_RESET_TIMER2, []() { timerReset(1); }); + resetMenu->addLine(STR_RESET_TIMER3, []() { timerReset(2); }); + resetMenu->addLine(STR_RESET_TELEMETRY, []() { telemetryReset(); }); + return 0; + }); carousel->addButton(ICON_STATS, STR_MAIN_MENU_STATISTICS, [=]() -> uint8_t { deleteLater(); @@ -101,34 +113,14 @@ ViewMainMenu::ViewMainMenu(Window* parent, std::function closeHandler) : return 0; }); - carousel->addButton(ICON_EDGETX, STR_MAIN_MENU_ABOUT_EDGETX, [=]() -> uint8_t { - deleteLater(); - new AboutUs(); - return 0; - }); + carousel->addButton(ICON_EDGETX, STR_MAIN_MENU_ABOUT_EDGETX, + [=]() -> uint8_t { + deleteLater(); + new AboutUs(); + return 0; + }); - auto carousel_obj = carousel->getLvObj(); - lv_obj_center(carousel_obj); - - lv_obj_update_layout(carousel_obj); - carouselRect.x = lv_obj_get_x(carousel_obj); - carouselRect.y = lv_obj_get_y(carousel_obj); - carouselRect.w = lv_obj_get_width(carousel_obj); - carouselRect.h = lv_obj_get_height(carousel_obj); - - // carousel->setCloseHandler([=]() { deleteLater(); }); - // carousel->setFocus(); -} - -uint16_t* lcdGetBackupBuffer(); - -void ViewMainMenu::paint(BitmapBuffer* dc) -{ - rect_t zone = carouselRect; - zone.x -= 8; zone.y -= 8; - zone.w += 16; zone.h += 16; - - dc->drawFilledRect(zone.x, zone.y, zone.w, zone.h, SOLID, BLACK, OPACITY(4)); + lv_obj_center(carousel->getLvObj()); } void ViewMainMenu::deleteLater(bool detach, bool trash) @@ -138,12 +130,6 @@ void ViewMainMenu::deleteLater(bool detach, bool trash) Window::deleteLater(detach, trash); } -void ViewMainMenu::onClicked() -{ - deleteLater(); -} +void ViewMainMenu::onClicked() { deleteLater(); } -void ViewMainMenu::onCancel() -{ - deleteLater(); -} +void ViewMainMenu::onCancel() { deleteLater(); } diff --git a/radio/src/gui/colorlcd/view_main_menu.h b/radio/src/gui/colorlcd/view_main_menu.h index 08dbfaa5d..fe4b15150 100644 --- a/radio/src/gui/colorlcd/view_main_menu.h +++ b/radio/src/gui/colorlcd/view_main_menu.h @@ -30,10 +30,8 @@ class ViewMainMenu : public Window void onCancel() override; void onClicked() override; - void paint(BitmapBuffer* dc) override; void deleteLater(bool detach = true, bool trash = true) override; protected: - rect_t carouselRect; std::function closeHandler = nullptr; }; diff --git a/radio/src/thirdparty/libopenui/src/widgets/etx_obj_create.h b/radio/src/thirdparty/libopenui/src/widgets/etx_obj_create.h index 8212b625e..874ac4614 100644 --- a/radio/src/thirdparty/libopenui/src/widgets/etx_obj_create.h +++ b/radio/src/thirdparty/libopenui/src/widgets/etx_obj_create.h @@ -35,9 +35,11 @@ lv_obj_t* etx_switch_create(lv_obj_t* parent); lv_obj_t* etx_slider_create(lv_obj_t* parent); lv_obj_t* etx_btnmatrix_create(lv_obj_t* parent); lv_obj_t* etx_button_create(lv_obj_t* parent); +lv_obj_t* etx_quick_button_create(lv_obj_t* parent); lv_obj_t* etx_menu_button_create(lv_obj_t* parent); lv_obj_t* etx_choice_create(lv_obj_t* parent); lv_obj_t* etx_modal_create(lv_obj_t* parent); +lv_obj_t* etx_modal_dialog_create(lv_obj_t* parent); lv_obj_t* etx_modal_content_create(lv_obj_t* parent); lv_obj_t* etx_modal_title_create(lv_obj_t* parent); lv_obj_t* etx_bar_create(lv_obj_t* parent);