This commit is contained in:
Thomas Peterson 2026-01-31 13:53:38 +01:00
parent da987838f5
commit bc7a3ad0b4
4 changed files with 62 additions and 1 deletions

View File

@ -41,6 +41,7 @@ ButtonWidget::ButtonWidget(const WidgetConfig& config)
, contentContainer_(nullptr)
, label_(nullptr)
, iconLabel_(nullptr)
, shadowObj_(nullptr)
{
}
@ -49,6 +50,11 @@ ButtonWidget::~ButtonWidget() {
if (obj_) {
lv_obj_remove_event_cb(obj_, clickCallback);
}
// Delete fake shadow (not a child of obj_, so must delete separately)
if (shadowObj_ && lv_obj_is_valid(shadowObj_)) {
lv_obj_delete(shadowObj_);
}
shadowObj_ = nullptr;
contentContainer_ = nullptr;
label_ = nullptr;
iconLabel_ = nullptr;
@ -128,6 +134,11 @@ void ButtonWidget::applyTextAlignment() {
}
lv_obj_t* ButtonWidget::create(lv_obj_t* parent) {
// Create fake shadow FIRST (so it's behind the button in z-order)
if (config_.shadow.enabled) {
createFakeShadow(parent);
}
obj_ = lv_btn_create(parent);
lv_obj_set_pos(obj_, config_.x, config_.y);
lv_obj_set_size(obj_, config_.width > 0 ? config_.width : 100,
@ -200,9 +211,12 @@ lv_obj_t* ButtonWidget::create(lv_obj_t* parent) {
void ButtonWidget::applyStyle() {
if (obj_ == nullptr) return;
// Apply common style to button
// Apply common style to button (shadows skipped for buttons in Widget::applyShadowStyle)
applyCommonStyle();
// Apply fake shadow style
applyFakeShadowStyle();
// Apply text style to label
if (label_ != nullptr) {
lv_obj_set_style_text_color(label_, lv_color_make(
@ -224,3 +238,47 @@ bool ButtonWidget::isChecked() const {
if (obj_ == nullptr) return false;
return (lv_obj_get_state(obj_) & LV_STATE_CHECKED) != 0;
}
void ButtonWidget::createFakeShadow(lv_obj_t* parent) {
// Create a simple rectangle as fake shadow (no LVGL shadow rendering)
shadowObj_ = lv_obj_create(parent);
if (!shadowObj_) return;
lv_obj_remove_style_all(shadowObj_);
lv_obj_clear_flag(shadowObj_, static_cast<lv_obj_flag_t>(LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE));
// Position: offset from button position by shadow offset
int16_t shadowX = config_.x + config_.shadow.offsetX;
int16_t shadowY = config_.y + config_.shadow.offsetY;
// Size: slightly larger than button (spread effect)
int16_t spread = config_.shadow.spread > 8 ? 8 : config_.shadow.spread;
int16_t shadowW = (config_.width > 0 ? config_.width : 100) + spread * 2;
int16_t shadowH = (config_.height > 0 ? config_.height : 50) + spread * 2;
// Adjust position for spread
shadowX -= spread;
shadowY -= spread;
lv_obj_set_pos(shadowObj_, shadowX, shadowY);
lv_obj_set_size(shadowObj_, shadowW, shadowH);
}
void ButtonWidget::applyFakeShadowStyle() {
if (!shadowObj_) return;
lv_color_t shadowColor = lv_color_make(
config_.shadow.color.r, config_.shadow.color.g, config_.shadow.color.b);
// Blur simulation: use lower opacity for softer look
uint8_t blur = config_.shadow.blur > 15 ? 15 : config_.shadow.blur;
uint8_t opa = blur > 0 ? (uint8_t)(120 - blur * 4) : 120; // Less blur = more solid
lv_obj_set_style_bg_color(shadowObj_, shadowColor, 0);
lv_obj_set_style_bg_opa(shadowObj_, opa, 0);
// Match button's border radius
if (config_.borderRadius > 0) {
lv_obj_set_style_radius(shadowObj_, config_.borderRadius + config_.shadow.spread, 0);
}
}

View File

@ -17,9 +17,12 @@ private:
lv_obj_t* contentContainer_ = nullptr;
lv_obj_t* label_ = nullptr;
lv_obj_t* iconLabel_ = nullptr;
lv_obj_t* shadowObj_ = nullptr; // Fake shadow rectangle behind button
void setupFlexLayout();
void applyTextAlignment();
void createFakeShadow(lv_obj_t* parent);
void applyFakeShadowStyle();
static int encodeUtf8(uint32_t codepoint, char* buf);
static void clickCallback(lv_event_t* e);
};