knxdisplay/main/widgets/ButtonMatrixWidget.cpp
2026-02-05 18:19:26 +01:00

158 lines
5.2 KiB
C++

#include "ButtonMatrixWidget.hpp"
#include "../WidgetManager.hpp"
#include <algorithm>
#include <cctype>
namespace {
std::string trimToken(const std::string& token) {
size_t start = 0;
size_t end = token.size();
while (start < end && std::isspace(static_cast<unsigned char>(token[start])) != 0) {
start++;
}
while (end > start && std::isspace(static_cast<unsigned char>(token[end - 1])) != 0) {
end--;
}
return token.substr(start, end - start);
}
}
ButtonMatrixWidget::ButtonMatrixWidget(const WidgetConfig& config)
: Widget(config)
{
}
ButtonMatrixWidget::~ButtonMatrixWidget() {
if (obj_) {
lv_obj_remove_event_cb(obj_, valueChangedCallback);
}
}
void ButtonMatrixWidget::rebuildMapStorage() {
mapStorage_.clear();
mapPointers_.clear();
auto addButton = [&](const std::string& token) {
std::string trimmed = trimToken(token);
if (!trimmed.empty()) {
mapStorage_.push_back(trimmed);
}
};
if (config_.text[0] != '\0') {
std::string token;
for (size_t i = 0; config_.text[i] != '\0'; ++i) {
const char ch = config_.text[i];
if (ch == ';' || ch == ',') {
addButton(token);
token.clear();
} else if (ch == '\n' || ch == '\r') {
addButton(token);
token.clear();
if (!mapStorage_.empty() && mapStorage_.back() != "\n") {
mapStorage_.push_back("\n");
}
if (ch == '\r' && config_.text[i + 1] == '\n') {
++i;
}
} else {
token.push_back(ch);
}
}
addButton(token);
while (!mapStorage_.empty() && mapStorage_.back() == "\n") {
mapStorage_.pop_back();
}
}
if (mapStorage_.empty()) {
mapStorage_ = {"1", "2", "3", "\n", "4", "5", "6", "\n", "7", "8", "9"};
}
mapPointers_.reserve(mapStorage_.size() + 1);
for (const std::string& entry : mapStorage_) {
mapPointers_.push_back(entry.c_str());
}
mapPointers_.push_back("");
}
lv_obj_t* ButtonMatrixWidget::create(lv_obj_t* parent) {
obj_ = lv_buttonmatrix_create(parent);
if (!obj_) return nullptr;
lv_obj_set_pos(obj_, config_.x, config_.y);
lv_obj_set_size(obj_,
config_.width > 0 ? config_.width : 220,
config_.height > 0 ? config_.height : 140);
lv_obj_clear_flag(obj_, LV_OBJ_FLAG_SCROLLABLE);
rebuildMapStorage();
lv_buttonmatrix_set_map(obj_, mapPointers_.data());
lv_buttonmatrix_set_button_ctrl_all(obj_, LV_BUTTONMATRIX_CTRL_CLICK_TRIG);
if (config_.isToggle) {
lv_buttonmatrix_set_button_ctrl_all(obj_, LV_BUTTONMATRIX_CTRL_CHECKABLE);
}
lv_obj_add_event_cb(obj_, valueChangedCallback, LV_EVENT_VALUE_CHANGED, this);
return obj_;
}
void ButtonMatrixWidget::applyStyle() {
if (!obj_) return;
applyCommonStyle();
lv_color_t textColor = lv_color_make(
config_.textColor.r, config_.textColor.g, config_.textColor.b);
lv_color_t buttonColor = lv_color_make(
config_.bgColor.r, config_.bgColor.g, config_.bgColor.b);
uint8_t buttonOpa = config_.bgOpacity > 0 ? config_.bgOpacity : static_cast<uint8_t>(LV_OPA_30);
lv_obj_set_style_text_font(obj_, getFontBySize(config_.fontSize), LV_PART_ITEMS);
lv_obj_set_style_text_color(obj_, textColor, LV_PART_ITEMS);
lv_obj_set_style_bg_color(obj_, buttonColor, LV_PART_ITEMS);
lv_obj_set_style_bg_opa(obj_, buttonOpa, LV_PART_ITEMS);
if (config_.borderRadius > 0) {
lv_obj_set_style_radius(obj_, config_.borderRadius, LV_PART_ITEMS);
}
if (config_.borderWidth > 0 && config_.borderOpacity > 0) {
lv_obj_set_style_border_width(obj_, config_.borderWidth, LV_PART_ITEMS);
lv_obj_set_style_border_color(obj_, lv_color_make(
config_.borderColor.r, config_.borderColor.g, config_.borderColor.b), LV_PART_ITEMS);
lv_obj_set_style_border_opa(obj_, config_.borderOpacity, LV_PART_ITEMS);
} else {
lv_obj_set_style_border_width(obj_, 0, LV_PART_ITEMS);
}
lv_style_selector_t pressedSel = static_cast<lv_style_selector_t>(LV_PART_ITEMS) |
static_cast<lv_style_selector_t>(LV_STATE_PRESSED);
lv_style_selector_t checkedSel = static_cast<lv_style_selector_t>(LV_PART_ITEMS) |
static_cast<lv_style_selector_t>(LV_STATE_CHECKED);
lv_obj_set_style_bg_color(obj_, textColor, pressedSel);
lv_obj_set_style_bg_opa(obj_, LV_OPA_40, pressedSel);
lv_obj_set_style_text_color(obj_, lv_color_white(), pressedSel);
lv_obj_set_style_bg_color(obj_, textColor, checkedSel);
lv_obj_set_style_bg_opa(obj_, LV_OPA_50, checkedSel);
lv_obj_set_style_text_color(obj_, lv_color_white(), checkedSel);
}
void ButtonMatrixWidget::valueChangedCallback(lv_event_t* e) {
ButtonMatrixWidget* widget = static_cast<ButtonMatrixWidget*>(lv_event_get_user_data(e));
if (!widget) return;
lv_obj_t* target = static_cast<lv_obj_t*>(lv_event_get_target(e));
WidgetManager::instance().handleButtonAction(widget->getConfig(), target);
}