From bc7a3ad0b44619359c491e954e28ace399a0c342 Mon Sep 17 00:00:00 2001 From: Thomas Peterson Date: Sat, 31 Jan 2026 13:53:38 +0100 Subject: [PATCH] Fixes --- .../ButtonWidget.hpp.551D0D3595AEDB81.idx | Bin 1244 -> 1456 bytes .../index/Widget.cpp.63DB7B9186B85891.idx | Bin 4960 -> 5162 bytes main/widgets/ButtonWidget.cpp | 60 +++++++++++++++++- main/widgets/ButtonWidget.hpp | 3 + 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/.cache/clangd/index/ButtonWidget.hpp.551D0D3595AEDB81.idx b/.cache/clangd/index/ButtonWidget.hpp.551D0D3595AEDB81.idx index 9175233a6bbd969a12edcdfd6265db2f71b43bdd..4cbad88cb9aad755e368a253cd1bac9c50c824ee 100644 GIT binary patch literal 1456 zcmY*Y3rrMO6n*oU-DP%WhuK+|{R!2D#!sOV+z>>xK^GM?_M;Ugw$xP`ts=0yDqC!t zijpWwOzIa@)K;L1si2g$22HKCkV>r@E2d)NC&n0;5RDr({@yG-G~Hz1%bauXoqO*& z^FiLUY0Wx9rY^~=C@Bsu;t3%Z_74R8%X--T8AnLPo*@fyUc?17+FIcJ;I+-Y%=Y__xPYKBlcd^QKbKb+zi~ zy2>9XoIcij^6c^2_mak4Y}%3gd1T|-c~yn=S2D*o);{Mmo_D`fw|{cnlOHa-_8#0{ z{^y45GYh(s3JMz6=A>s%Z7N= z**q+IkXSY``#HM5OiR45$)r*v9YjP&oWlWn;)3E&Rwth`D^v$MUWj*ruKYg5_lvJE zUZFf_qhPdvuDz1e(Q>|TluS+R-KwnGqX+2Lf$wgmG@Dc7DTi#mNk8=Nmn*+0^?ta0 zg+gOM+XZ_9vQv-ro$}O2N);-DHVGybbVowT`OYS;T%iJJn_wF%o^&VYY)fe3CWXd= z7Gz-xUeBx1g9yuKxE zDF?6HsEYCi-k?K%Mt)8AyN;H7GBvRBimbd5JwT`Dgn#ez9}25fk8G#n9GZN_2=X>R zW@*1d70_0}YDc!e_|w1~MnHMa7*!lSLvc=sDh(J)Ggwm?FcfC6rYvA6%W7+~0*0b2 zT2m5mq<3cBoW)(aoFwwYc{gAP%%U}60Yg{@Yk~q^f1X>-FfxLF69XV3v&!eGrSfKh|(LNf~B z*vF$s-7nhqH5=NQ=o}4ALB|*eEi?Gh5$S&mlSG5gU`FU)<>8N-Hq;(qmGmR@DOfT* z#&M$NEkqkz270pVUfyNV4yVHnxv>-0rRFz8qb)X*W--997=txy0Ve+96^p#AWxcl} zm|hu}#9=3pm>{%pURyYLsqrX>Hj`I1>`VTw{{#n11^kNxHf?To!s#gqJ=%5%bEvTN54aGt+lZqw`K0G!G=_X(|j0grOiO{Ti;_ zDRF0olXaYkrQ{TW6s$sNSqLlK8-5&mPWo#GisU?HMJ*yoWutNcI()ls?@^Bz3XY~(0$uVpvZJ}zx%?JWz?ZButgeHs(TXW-4*Lmb5bEk|-5vX_32>}oCuFXAXE(1=A!pjU5kf25y`E0Q)RYb6OKGVX@`DqLd$bPC6D%dcwR0@zYFU5|h%~=6>Fdor zC5CJ@r*;84-i`31S7c3c6brNxDeZwK^tw#L^gr&9GK(uvG`K<{iyHug8yFT`02o}r zu%JG`pgulZkRD)A9Y+gl13WvDRJl2$djrWJ+L?9-7)-#?g7^TRZhtV+>D_o(%pgP~ z2E4$3cF5)LA4hWx2+1G?tzcjr8N|~(10_NRzD4j5Zn2v2^8B)=>?*EFtxp6ZLJ{5g)JRgNlm za05EQf(r8h(NGpHUKjy@VFWNNSP!sXmz@@aE0)A`7y}9oYe?uF3?Lvfb?bez@l8Vu o2~~O=sj2pOKG{x!;Rbz%K`nGI`z-<9&@r#ZVCM;wl9Um@0ALeiCjbBd diff --git a/.cache/clangd/index/Widget.cpp.63DB7B9186B85891.idx b/.cache/clangd/index/Widget.cpp.63DB7B9186B85891.idx index 2c96fe4f2579613b4d2e06e6af86ef458e8fa1d7..fcdc0f4d2600795f638dabc504a2087c46c53d2d 100644 GIT binary patch literal 5162 zcmY*b2{@G9+n+OLG-J#d%ouAZ%VZB@pRtT3resDcrpOjr6r<8hi;`ALi6RkM>P>Hp zP+8g#kqQ;PsU(v2w^TxX&y(xS_x$I&=DMEWeSYWO&VAqKh`c>LXEAU%euQ`8+Q@`Z z0uF~$M*fn7_!#009InwEhf6GI$QMgqURK&ZB_7^z$IhbdL))UyFV=fIfsQAy;)gx- zD_htX^mFw1y}PI0S43#Kt#lhD%$dNKl>O?tTC2Xf@#8q}U;?qr+&(4t*VviY6YA}n z2}?vdXB#&p``z3fHZVT5|5%?%;fa4;ceD&-+Px|KHS2&uT-VxbD!#V@KmMIGJU->> z;BhiodupU;+r*%J^+La-%!gagxl?(YE1GI@yI(8SMjvf#-g@ww!G~AkPRaOZyMhvn z1v9E@qpuA;>gblaBK}X3-YvA#Xld*HGI1+##`34`Cwb}~EbpU}wYkN?PHLV<*oB=X zi92Myl?>U(^&h;l>{n6MBj+3J3{7~>xmN04_&oC`-(UQ_eYA4JqtPF!J`Lk9$EV(U zCw~@b1iROD_U^5Dv~kq~u6oAJuX1G%?zw*d`f4)M(_ybL(Q5zg0h7_rBscCI5%&i-LjxSqp_;r$Z zRnvpjFp-qNd`7!(?RzrmFs)_atC6ql#JKI7fBUjE4!78P_ji`NSdu1o68iNYtjRhd zd|Kzrb(YJmPjxZhyf@%JUSE&x!Md?A5nolq4kW0V6QizQlB;<;S4T%LVyVo9;`_cT zez{C0&^Rz0P~$Fl^ko-$UHWO}jKeNRBa#|k5oY)#zun_+Xksf*jZdi>oTFwg=&Vfd z%h0$ff3lL%#ms!s!8BqWt_zO|%6~X08&yXNDL!nx2+#~-ZW&o!Fk60ukh`ny0z<94 zb1A;gt*t9BVBh7prXB^ z?~dM&*-4j0V)ojcxnsV~eBnP2W-#eTHNPKK~@;U+$r(fu-U(NuBi z@}A1H`lrE#g}mJ=EAmXWW1&o0=0)Nl!VDeTx+>_&Knpg;u~KDVub}P6keX_uZ(G7#Nmv zUUb5_Y~ARmovDXblh}beReOK`J4QInb@|qEOfQOgb?v*oU{pC%o%4z* znlyiS3}3S&VJ|u4BV|+%l<7ZDyvIxIZ+fQceDi)s7EV{fP>tE|H|{woPX6^GukS0D z#Oq4ucV1d$y35XU^VEcDuYbmcp@y@a$(M42X-_VVg=KeLyD|7~pV8f+VNd#(kJPBg z@8&G`KW0*g%rIFMTL6JA1=}Hx27p9DvQ+$j1-MDAjRYF zmUH>u0j+fWy=jUjRTH6@Dw;|uPZ9zY-TKT&l<;?^DN$-s2CcwW({>Kj@~Hb*GVVy| z7#)9inxaS5L-Jy-XfDl5eB?^WZ!!*d$fhFY*#iS0BYzuk)Hxb3UkK!CaGl!40GdTaxDKvg!|YzB-^G5=UG=U8CWa?QC| zDCUT5pcPLh!*fWL&-$ayip_=EUS?*LYHfO@hH4YD#F~(gLUXY-7J7;2Ls(dFhpX6m zOB>b3C-JqR53pMCh@3*8P~btzP1o(WUO~Qpc&kTTP)6zJ`)_8W+oNQo6ky1#i5znM z+n0u@Gu8&yR!}Vho!Cws3=Gl=GJ?*03~$of<$q`ns!hNXxIsBP;NXza^>X7siK27V zFxxr$95XC*;P4@Y-2@Py(MEzkM_)6quRF8A4z&{I5atT4w52+^hO}flpjNmH?*AOR zAs1_f>%et|Rx5*uJL*>F*LIY^!xc5J2wEp_+#zf>q zSt1pBi9imCqX5;SP>Z97g_az9479VdbHG4Hk|TC6SDvekS>Qh$;G?IwXk|Fsou6u^|@PiJdVp%s9*v z1H+BOrLZR`Mxl6@tjC`^@f7$$8a!bd;urx(kj3N{TL8$a98OLamNW{0%Yks+cV{ z!$KFaCkBRDh1p|ZxK+3muH(mx#j%IxDe zDPzg1BvpA#Zs(Hb%3~5@tz(UC0XuEG*_c(QSx(rh=IQXTWWEj`3k4*BJSMc@S;5kl zL?Q~&3DLu>u9&p~yBaz>6kDia`eAc0f}1fdr-tT9*-=x9Q3 zXDEksbh{csjR7-*(9jzi(w5D?(SG@QZU_OP`Ooyd zG?^^a4M(~o_AcO=@ob@2_v79#uh^AQjBY0|3A(Uct=!#;x|@WJ&|-eeM?Hs%hO7Dg~}D>71iJzfcnrw zw9~hjg+A_} z9&pJ1rfb{J36yV5u$JD@x%<3xer(GBjmm=w!P0PW@sVpn(FeICK3rmhezYPFc=&6< ze7F7oH@FS@Mi#vv!aoj>X$38y4TP_aSOXA3J!k}VKn71&R8nTBs;O&eYR%Nv(Vev) zWPyWVJ6OGDZFJ14SWmBc9^URg^Zge1E)>K|Htq(gU>8UOaqHGE7cUDk4h~%rvIB%| zO5FU{wyjCYTLN6&oR-=YgHmt^oCGD{04M?(AQLQ}t*37gXvQ(OGMVeJ6FAzL+H&nJ zoc97tYZu;e5FSwo3P1{2k`DL@kt?J2fem|r$bXSA7vz9EkPQxlIYw;5Bj6}F22Ox{ zPzEl53UCVi1I~f7;0!noD#1l?9{de1fof0-%E47ogM>&R%F0pXsWb(q3Tp<5d>J%@ LDsTmW27voNZDKo% literal 4960 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 diff --git a/main/widgets/ButtonWidget.cpp b/main/widgets/ButtonWidget.cpp index 0e5eff3..265d3a4 100644 --- a/main/widgets/ButtonWidget.cpp +++ b/main/widgets/ButtonWidget.cpp @@ -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_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); + } +} diff --git a/main/widgets/ButtonWidget.hpp b/main/widgets/ButtonWidget.hpp index ceaa638..1eab728 100644 --- a/main/widgets/ButtonWidget.hpp +++ b/main/widgets/ButtonWidget.hpp @@ -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); };