117 lines
3.8 KiB
C++
117 lines
3.8 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);
|
|
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,
|
|
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);
|
|
}
|
|
}
|