knxdisplay/main/widgets/IconWidget.cpp
2026-01-25 15:20:12 +01:00

113 lines
3.7 KiB
C++

#include "IconWidget.hpp"
#include "../Fonts.hpp"
#include "esp_log.h"
static const char* TAG = "IconWidget";
IconWidget::IconWidget(const WidgetConfig& config)
: Widget(config)
, iconLabel_(nullptr)
{
}
int IconWidget::encodeUtf8(uint32_t codepoint, char* buf) {
if (codepoint < 0x80) {
buf[0] = static_cast<char>(codepoint);
buf[1] = '\0';
return 1;
} else if (codepoint < 0x800) {
buf[0] = static_cast<char>(0xC0 | (codepoint >> 6));
buf[1] = static_cast<char>(0x80 | (codepoint & 0x3F));
buf[2] = '\0';
return 2;
} else if (codepoint < 0x10000) {
buf[0] = static_cast<char>(0xE0 | (codepoint >> 12));
buf[1] = static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F));
buf[2] = static_cast<char>(0x80 | (codepoint & 0x3F));
buf[3] = '\0';
return 3;
} else if (codepoint < 0x110000) {
buf[0] = static_cast<char>(0xF0 | (codepoint >> 18));
buf[1] = static_cast<char>(0x80 | ((codepoint >> 12) & 0x3F));
buf[2] = static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F));
buf[3] = static_cast<char>(0x80 | (codepoint & 0x3F));
buf[4] = '\0';
return 4;
}
buf[0] = '\0';
return 0;
}
lv_obj_t* IconWidget::create(lv_obj_t* parent) {
// Create container for the icon
obj_ = lv_obj_create(parent);
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,
config_.height > 0 ? config_.height : 48);
// Create icon label
iconLabel_ = lv_label_create(obj_);
if (config_.iconCodepoint > 0) {
char iconText[5];
encodeUtf8(config_.iconCodepoint, iconText);
lv_label_set_text(iconLabel_, iconText);
} else {
lv_label_set_text(iconLabel_, "?");
}
lv_obj_center(iconLabel_);
ESP_LOGI(TAG, "Created icon widget (codepoint: 0x%lx) at %d,%d",
(unsigned long)config_.iconCodepoint, config_.x, config_.y);
return obj_;
}
void IconWidget::applyStyle() {
if (obj_ == nullptr) return;
// Background
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);
}
// Border radius
if (config_.borderRadius > 0) {
lv_obj_set_style_radius(obj_, config_.borderRadius, 0);
}
// Apply icon style
if (iconLabel_ != nullptr) {
lv_obj_set_style_text_color(iconLabel_, lv_color_make(
config_.textColor.r, config_.textColor.g, config_.textColor.b), 0);
// Use icon font
uint8_t sizeIdx = config_.iconSize < 6 ? config_.iconSize : config_.fontSize;
if (Fonts::hasIconFont()) {
lv_obj_set_style_text_font(iconLabel_, Fonts::iconFont(sizeIdx), 0);
} else {
// Fallback to text font (won't show correct icon, but won't crash)
lv_obj_set_style_text_font(iconLabel_, Fonts::bySizeIndex(sizeIdx), 0);
}
}
}
void IconWidget::onKnxSwitch(bool value) {
if (iconLabel_ == nullptr) return;
if (config_.textSource != TextSource::KNX_DPT_SWITCH) return;
// Change icon color based on switch state
if (value) {
// Use text color for "on" state (default)
lv_obj_set_style_text_color(iconLabel_, lv_color_make(
config_.textColor.r, config_.textColor.g, config_.textColor.b), 0);
} else {
// Dim color for "off" state (50% brightness)
lv_obj_set_style_text_color(iconLabel_, lv_color_make(
config_.textColor.r / 2, config_.textColor.g / 2, config_.textColor.b / 2), 0);
}
}