This commit is contained in:
Thomas Peterson 2026-01-26 13:47:45 +01:00
parent 738d7d3baf
commit 2ae3335031
18 changed files with 67 additions and 39 deletions

View File

@ -311,11 +311,13 @@ void WidgetManager::showModalScreen(const ScreenConfig& screen) {
lv_obj_t* dimmer = nullptr; lv_obj_t* dimmer = nullptr;
if (screen.modalDimBackground) { if (screen.modalDimBackground) {
dimmer = lv_obj_create(lv_layer_top()); dimmer = lv_obj_create(lv_layer_top());
lv_obj_remove_style_all(dimmer); if (dimmer) {
lv_obj_set_size(dimmer, dispWidth, dispHeight); lv_obj_remove_style_all(dimmer);
lv_obj_set_style_bg_color(dimmer, lv_color_black(), 0); lv_obj_set_size(dimmer, dispWidth, dispHeight);
lv_obj_set_style_bg_opa(dimmer, LV_OPA_50, 0); lv_obj_set_style_bg_color(dimmer, lv_color_black(), 0);
lv_obj_clear_flag(dimmer, LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_style_bg_opa(dimmer, LV_OPA_50, 0);
lv_obj_clear_flag(dimmer, LV_OBJ_FLAG_SCROLLABLE);
}
} }
// Create modal container // Create modal container
@ -611,10 +613,11 @@ void WidgetManager::onUserActivity() {
} }
void WidgetManager::destroyAllWidgets() { void WidgetManager::destroyAllWidgets() {
ESP_LOGI(TAG, "destroyAllWidgets: Start"); ESP_LOGI(TAG, "destroyAllWidgets: Start (%d widgets)", widgets_.size());
for (size_t i = 0; i < widgets_.size(); i++) { // Destroy in reverse order (last created first)
for (int i = static_cast<int>(widgets_.size()) - 1; i >= 0; i--) {
if (widgets_[i]) { if (widgets_[i]) {
// ESP_LOGI(TAG, "Destroying widget %d", i); ESP_LOGD(TAG, "Destroying widget %d", i);
widgets_[i].reset(); widgets_[i].reset();
} }
} }

View File

@ -94,6 +94,9 @@ lv_obj_t* ButtonWidget::create(lv_obj_t* parent) {
if (hasIcon) { if (hasIcon) {
// Create container for flex layout // Create container for flex layout
contentContainer_ = lv_obj_create(obj_); contentContainer_ = lv_obj_create(obj_);
if (contentContainer_ == nullptr) {
return obj_; // Continue without icon container
}
lv_obj_remove_style_all(contentContainer_); lv_obj_remove_style_all(contentContainer_);
lv_obj_set_size(contentContainer_, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_obj_set_size(contentContainer_, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_center(contentContainer_); lv_obj_center(contentContainer_);

View File

@ -41,6 +41,10 @@ int IconWidget::encodeUtf8(uint32_t codepoint, char* buf) {
lv_obj_t* IconWidget::create(lv_obj_t* parent) { lv_obj_t* IconWidget::create(lv_obj_t* parent) {
// Create container for the icon // Create container for the icon
obj_ = lv_obj_create(parent); 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_remove_style_all(obj_);
lv_obj_set_pos(obj_, config_.x, config_.y); lv_obj_set_pos(obj_, config_.x, config_.y);
lv_obj_set_size(obj_, config_.width > 0 ? config_.width : 48, lv_obj_set_size(obj_, config_.width > 0 ? config_.width : 48,

View File

@ -57,10 +57,14 @@ void LabelWidget::setupFlexLayout() {
lv_obj_t* LabelWidget::create(lv_obj_t* parent) { lv_obj_t* LabelWidget::create(lv_obj_t* parent) {
bool hasIcon = config_.iconCodepoint > 0 && Fonts::hasIconFont(); bool hasIcon = config_.iconCodepoint > 0 && Fonts::hasIconFont();
bool needsContainer = hasIcon || config_.bgOpacity > 0 || config_.borderRadius > 0;
if (hasIcon) { if (needsContainer) {
// Create container object for flex layout // Create container object for background/radius/flex layout
obj_ = lv_obj_create(parent); obj_ = lv_obj_create(parent);
if (obj_ == nullptr) {
return nullptr;
}
lv_obj_remove_style_all(obj_); lv_obj_remove_style_all(obj_);
lv_obj_set_pos(obj_, config_.x, config_.y); lv_obj_set_pos(obj_, config_.x, config_.y);
if (config_.width > 0 && config_.height > 0) { if (config_.width > 0 && config_.height > 0) {
@ -71,30 +75,37 @@ lv_obj_t* LabelWidget::create(lv_obj_t* parent) {
container_ = obj_; container_ = obj_;
// Create elements in correct order based on icon position if (hasIcon) {
bool iconFirst = (config_.iconPosition == static_cast<uint8_t>(IconPosition::LEFT) || // Create elements in correct order based on icon position
config_.iconPosition == static_cast<uint8_t>(IconPosition::TOP)); bool iconFirst = (config_.iconPosition == static_cast<uint8_t>(IconPosition::LEFT) ||
config_.iconPosition == static_cast<uint8_t>(IconPosition::TOP));
if (iconFirst) { if (iconFirst) {
iconLabel_ = lv_label_create(container_); iconLabel_ = lv_label_create(container_);
char iconText[5]; char iconText[5];
encodeUtf8(config_.iconCodepoint, iconText); encodeUtf8(config_.iconCodepoint, iconText);
lv_label_set_text(iconLabel_, 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 { } else {
// Simple label without icon // Simple label without container
obj_ = lv_label_create(parent); obj_ = lv_label_create(parent);
textLabel_ = obj_; textLabel_ = obj_;
lv_label_set_text(obj_, config_.text); lv_label_set_text(obj_, config_.text);
@ -110,11 +121,16 @@ lv_obj_t* LabelWidget::create(lv_obj_t* parent) {
void LabelWidget::applyStyle() { void LabelWidget::applyStyle() {
if (obj_ == nullptr) return; if (obj_ == nullptr) return;
// Apply background if container // Apply background and border radius if container exists
if (container_ != nullptr && config_.bgOpacity > 0) { if (container_ != nullptr) {
lv_obj_set_style_bg_color(obj_, lv_color_make( if (config_.bgOpacity > 0) {
config_.bgColor.r, config_.bgColor.g, config_.bgColor.b), 0); lv_obj_set_style_bg_color(obj_, lv_color_make(
lv_obj_set_style_bg_opa(obj_, config_.bgOpacity, 0); 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 // Apply text style

View File

@ -13,7 +13,9 @@ Widget::~Widget() {
void Widget::destroy() { void Widget::destroy() {
if (obj_ != nullptr) { if (obj_ != nullptr) {
lv_obj_delete(obj_); if (lv_obj_is_valid(obj_)) {
lv_obj_delete(obj_);
}
obj_ = nullptr; obj_ = nullptr;
} }
} }
@ -62,7 +64,7 @@ void Widget::applyCommonStyle() {
} }
void Widget::applyShadowStyle() { void Widget::applyShadowStyle() {
return;
if (obj_ == nullptr || !config_.shadow.enabled) return; if (obj_ == nullptr || !config_.shadow.enabled) return;
lv_obj_set_style_shadow_color(obj_, lv_color_make( lv_obj_set_style_shadow_color(obj_, lv_color_make(