diff --git a/.cache/clangd/index/ButtonWidget.cpp.6932614AE5FC71F9.idx b/.cache/clangd/index/ButtonWidget.cpp.6932614AE5FC71F9.idx index d22bc34..831033b 100644 Binary files a/.cache/clangd/index/ButtonWidget.cpp.6932614AE5FC71F9.idx and b/.cache/clangd/index/ButtonWidget.cpp.6932614AE5FC71F9.idx differ diff --git a/.cache/clangd/index/FileManagerHandlers.cpp.2F53BB33AABE7329.idx b/.cache/clangd/index/FileManagerHandlers.cpp.2F53BB33AABE7329.idx index e37f450..2c32b61 100644 Binary files a/.cache/clangd/index/FileManagerHandlers.cpp.2F53BB33AABE7329.idx and b/.cache/clangd/index/FileManagerHandlers.cpp.2F53BB33AABE7329.idx differ diff --git a/.cache/clangd/index/Fonts.cpp.63891DD6EC3699BC.idx b/.cache/clangd/index/Fonts.cpp.63891DD6EC3699BC.idx index f58527a..e568f1e 100644 Binary files a/.cache/clangd/index/Fonts.cpp.63891DD6EC3699BC.idx and b/.cache/clangd/index/Fonts.cpp.63891DD6EC3699BC.idx differ diff --git a/.cache/clangd/index/TabPageWidget.cpp.8BA3B0713CBB6420.idx b/.cache/clangd/index/TabPageWidget.cpp.8BA3B0713CBB6420.idx new file mode 100644 index 0000000..5f70b51 Binary files /dev/null and b/.cache/clangd/index/TabPageWidget.cpp.8BA3B0713CBB6420.idx differ diff --git a/.cache/clangd/index/TabPageWidget.hpp.CE81E6A9CA717A71.idx b/.cache/clangd/index/TabPageWidget.hpp.CE81E6A9CA717A71.idx new file mode 100644 index 0000000..c669a68 Binary files /dev/null and b/.cache/clangd/index/TabPageWidget.hpp.CE81E6A9CA717A71.idx differ diff --git a/.cache/clangd/index/TabViewWidget.cpp.02B5E93619762840.idx b/.cache/clangd/index/TabViewWidget.cpp.02B5E93619762840.idx new file mode 100644 index 0000000..a1384ff Binary files /dev/null and b/.cache/clangd/index/TabViewWidget.cpp.02B5E93619762840.idx differ diff --git a/.cache/clangd/index/TabViewWidget.hpp.0A33CC2822D2A0FA.idx b/.cache/clangd/index/TabViewWidget.hpp.0A33CC2822D2A0FA.idx new file mode 100644 index 0000000..55992e6 Binary files /dev/null and b/.cache/clangd/index/TabViewWidget.hpp.0A33CC2822D2A0FA.idx differ diff --git a/.cache/clangd/index/Widget.cpp.63DB7B9186B85891.idx b/.cache/clangd/index/Widget.cpp.63DB7B9186B85891.idx index ef16cff..a0244b2 100644 Binary files a/.cache/clangd/index/Widget.cpp.63DB7B9186B85891.idx and b/.cache/clangd/index/Widget.cpp.63DB7B9186B85891.idx differ diff --git a/.cache/clangd/index/Widget.hpp.63E5D98A9B23E60F.idx b/.cache/clangd/index/Widget.hpp.63E5D98A9B23E60F.idx index 64e6887..5f3cf10 100644 Binary files a/.cache/clangd/index/Widget.hpp.63E5D98A9B23E60F.idx and b/.cache/clangd/index/Widget.hpp.63E5D98A9B23E60F.idx differ diff --git a/.cache/clangd/index/WidgetConfig.cpp.FD56F9F36C29A5DA.idx b/.cache/clangd/index/WidgetConfig.cpp.FD56F9F36C29A5DA.idx index 43d12a0..17adf63 100644 Binary files a/.cache/clangd/index/WidgetConfig.cpp.FD56F9F36C29A5DA.idx and b/.cache/clangd/index/WidgetConfig.cpp.FD56F9F36C29A5DA.idx differ diff --git a/.cache/clangd/index/WidgetConfig.hpp.CAEFE2EEEB2A6996.idx b/.cache/clangd/index/WidgetConfig.hpp.CAEFE2EEEB2A6996.idx index 9262939..1911690 100644 Binary files a/.cache/clangd/index/WidgetConfig.hpp.CAEFE2EEEB2A6996.idx and b/.cache/clangd/index/WidgetConfig.hpp.CAEFE2EEEB2A6996.idx differ diff --git a/.cache/clangd/index/WidgetFactory.cpp.1026CAEFCA630F22.idx b/.cache/clangd/index/WidgetFactory.cpp.1026CAEFCA630F22.idx index f7534e0..bef00f5 100644 Binary files a/.cache/clangd/index/WidgetFactory.cpp.1026CAEFCA630F22.idx and b/.cache/clangd/index/WidgetFactory.cpp.1026CAEFCA630F22.idx differ diff --git a/.cache/clangd/index/WidgetManager.cpp.D8CE609DC911F13E.idx b/.cache/clangd/index/WidgetManager.cpp.D8CE609DC911F13E.idx index e042f6b..d576d2c 100644 Binary files a/.cache/clangd/index/WidgetManager.cpp.D8CE609DC911F13E.idx and b/.cache/clangd/index/WidgetManager.cpp.D8CE609DC911F13E.idx differ diff --git a/main/WidgetManager.cpp b/main/WidgetManager.cpp index 6bcca13..0ca9610 100644 --- a/main/WidgetManager.cpp +++ b/main/WidgetManager.cpp @@ -311,11 +311,13 @@ void WidgetManager::showModalScreen(const ScreenConfig& screen) { lv_obj_t* dimmer = nullptr; if (screen.modalDimBackground) { dimmer = lv_obj_create(lv_layer_top()); - lv_obj_remove_style_all(dimmer); - lv_obj_set_size(dimmer, dispWidth, dispHeight); - lv_obj_set_style_bg_color(dimmer, lv_color_black(), 0); - lv_obj_set_style_bg_opa(dimmer, LV_OPA_50, 0); - lv_obj_clear_flag(dimmer, LV_OBJ_FLAG_SCROLLABLE); + if (dimmer) { + lv_obj_remove_style_all(dimmer); + lv_obj_set_size(dimmer, dispWidth, dispHeight); + lv_obj_set_style_bg_color(dimmer, lv_color_black(), 0); + lv_obj_set_style_bg_opa(dimmer, LV_OPA_50, 0); + lv_obj_clear_flag(dimmer, LV_OBJ_FLAG_SCROLLABLE); + } } // Create modal container @@ -611,10 +613,11 @@ void WidgetManager::onUserActivity() { } void WidgetManager::destroyAllWidgets() { - ESP_LOGI(TAG, "destroyAllWidgets: Start"); - for (size_t i = 0; i < widgets_.size(); i++) { + ESP_LOGI(TAG, "destroyAllWidgets: Start (%d widgets)", widgets_.size()); + // Destroy in reverse order (last created first) + for (int i = static_cast(widgets_.size()) - 1; i >= 0; i--) { if (widgets_[i]) { - // ESP_LOGI(TAG, "Destroying widget %d", i); + ESP_LOGD(TAG, "Destroying widget %d", i); widgets_[i].reset(); } } diff --git a/main/widgets/ButtonWidget.cpp b/main/widgets/ButtonWidget.cpp index 1c7dd14..b76cad5 100644 --- a/main/widgets/ButtonWidget.cpp +++ b/main/widgets/ButtonWidget.cpp @@ -94,6 +94,9 @@ lv_obj_t* ButtonWidget::create(lv_obj_t* parent) { if (hasIcon) { // Create container for flex layout contentContainer_ = lv_obj_create(obj_); + if (contentContainer_ == nullptr) { + return obj_; // Continue without icon container + } lv_obj_remove_style_all(contentContainer_); lv_obj_set_size(contentContainer_, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_obj_center(contentContainer_); diff --git a/main/widgets/IconWidget.cpp b/main/widgets/IconWidget.cpp index 18a14bd..71b9d9e 100644 --- a/main/widgets/IconWidget.cpp +++ b/main/widgets/IconWidget.cpp @@ -41,6 +41,10 @@ int IconWidget::encodeUtf8(uint32_t codepoint, char* buf) { lv_obj_t* IconWidget::create(lv_obj_t* parent) { // Create container for the icon obj_ = lv_obj_create(parent); + if (obj_ == nullptr) { + ESP_LOGE(TAG, "Failed to create icon widget object"); + return nullptr; + } lv_obj_remove_style_all(obj_); lv_obj_set_pos(obj_, config_.x, config_.y); lv_obj_set_size(obj_, config_.width > 0 ? config_.width : 48, diff --git a/main/widgets/LabelWidget.cpp b/main/widgets/LabelWidget.cpp index 5851ec5..36aa585 100644 --- a/main/widgets/LabelWidget.cpp +++ b/main/widgets/LabelWidget.cpp @@ -57,10 +57,14 @@ void LabelWidget::setupFlexLayout() { lv_obj_t* LabelWidget::create(lv_obj_t* parent) { bool hasIcon = config_.iconCodepoint > 0 && Fonts::hasIconFont(); + bool needsContainer = hasIcon || config_.bgOpacity > 0 || config_.borderRadius > 0; - if (hasIcon) { - // Create container object for flex layout + if (needsContainer) { + // Create container object for background/radius/flex layout obj_ = lv_obj_create(parent); + if (obj_ == nullptr) { + return nullptr; + } lv_obj_remove_style_all(obj_); lv_obj_set_pos(obj_, config_.x, config_.y); if (config_.width > 0 && config_.height > 0) { @@ -71,30 +75,37 @@ lv_obj_t* LabelWidget::create(lv_obj_t* parent) { container_ = obj_; - // Create elements in correct order based on icon position - bool iconFirst = (config_.iconPosition == static_cast(IconPosition::LEFT) || - config_.iconPosition == static_cast(IconPosition::TOP)); + if (hasIcon) { + // Create elements in correct order based on icon position + bool iconFirst = (config_.iconPosition == static_cast(IconPosition::LEFT) || + config_.iconPosition == static_cast(IconPosition::TOP)); - if (iconFirst) { - iconLabel_ = lv_label_create(container_); - char iconText[5]; - encodeUtf8(config_.iconCodepoint, iconText); - lv_label_set_text(iconLabel_, iconText); + if (iconFirst) { + iconLabel_ = lv_label_create(container_); + char iconText[5]; + encodeUtf8(config_.iconCodepoint, iconText); + lv_label_set_text(iconLabel_, iconText); + } + + textLabel_ = lv_label_create(container_); + lv_label_set_text(textLabel_, config_.text); + + if (!iconFirst) { + iconLabel_ = lv_label_create(container_); + char iconText[5]; + encodeUtf8(config_.iconCodepoint, iconText); + lv_label_set_text(iconLabel_, iconText); + } + + setupFlexLayout(); + } else { + // Container with just text label (for bg/radius) + textLabel_ = lv_label_create(container_); + lv_label_set_text(textLabel_, config_.text); + lv_obj_center(textLabel_); } - - textLabel_ = lv_label_create(container_); - lv_label_set_text(textLabel_, config_.text); - - if (!iconFirst) { - iconLabel_ = lv_label_create(container_); - char iconText[5]; - encodeUtf8(config_.iconCodepoint, iconText); - lv_label_set_text(iconLabel_, iconText); - } - - setupFlexLayout(); } else { - // Simple label without icon + // Simple label without container obj_ = lv_label_create(parent); textLabel_ = obj_; lv_label_set_text(obj_, config_.text); @@ -110,11 +121,16 @@ lv_obj_t* LabelWidget::create(lv_obj_t* parent) { void LabelWidget::applyStyle() { if (obj_ == nullptr) return; - // Apply background if container - if (container_ != nullptr && config_.bgOpacity > 0) { - lv_obj_set_style_bg_color(obj_, lv_color_make( - config_.bgColor.r, config_.bgColor.g, config_.bgColor.b), 0); - lv_obj_set_style_bg_opa(obj_, config_.bgOpacity, 0); + // Apply background and border radius if container exists + if (container_ != nullptr) { + if (config_.bgOpacity > 0) { + lv_obj_set_style_bg_color(obj_, lv_color_make( + config_.bgColor.r, config_.bgColor.g, config_.bgColor.b), 0); + lv_obj_set_style_bg_opa(obj_, config_.bgOpacity, 0); + } + if (config_.borderRadius > 0) { + lv_obj_set_style_radius(obj_, config_.borderRadius, 0); + } } // Apply text style diff --git a/main/widgets/Widget.cpp b/main/widgets/Widget.cpp index 31c86a1..834bacb 100644 --- a/main/widgets/Widget.cpp +++ b/main/widgets/Widget.cpp @@ -13,7 +13,9 @@ Widget::~Widget() { void Widget::destroy() { if (obj_ != nullptr) { - lv_obj_delete(obj_); + if (lv_obj_is_valid(obj_)) { + lv_obj_delete(obj_); + } obj_ = nullptr; } } @@ -62,9 +64,9 @@ void Widget::applyCommonStyle() { } void Widget::applyShadowStyle() { - return; + if (obj_ == nullptr || !config_.shadow.enabled) return; - + lv_obj_set_style_shadow_color(obj_, lv_color_make( config_.shadow.color.r, config_.shadow.color.g, config_.shadow.color.b), 0); lv_obj_set_style_shadow_opa(obj_, 180, 0);