From d33320b7e5cb2c53525a00d6b91191ecc8218e36 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 2 Sep 2025 13:00:00 +0200 Subject: [PATCH] feat(image): add data binding to image src --- docs/src/details/widgets/image.rst | 8 ++-- src/others/xml/parsers/lv_xml_image_parser.c | 21 ++++++++--- src/widgets/image/lv_image.c | 39 +++++++++++++++++++- src/widgets/image/lv_image.h | 12 ++++++ xmls/lv_image.xml | 1 + 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/docs/src/details/widgets/image.rst b/docs/src/details/widgets/image.rst index b17ab677d5..bac3a7189e 100644 --- a/docs/src/details/widgets/image.rst +++ b/docs/src/details/widgets/image.rst @@ -200,13 +200,13 @@ Data binding To get familiar with observers, subjects, and data bindings in general visit the :ref:`Observer ` page. -This method of subscribing to a pointer Subject affects an Image Widget's source (``src``) +This method of subscribing to a pointer Subject affects a Image Widget's source (``src``) value directly. Note that this is a one-way binding (Subject ==> Widget) so when -the subject changes the Image will be update too. +the subject changes, the Image will be updated too. -It support only pointer subjects. +It supports only pointer subjects. -- :cpp:expr:`lv_image_bind_src(slider, &subject)` +- :cpp:expr:`lv_image_bind_src(img, &subject)` .. _lv_image_events: diff --git a/src/others/xml/parsers/lv_xml_image_parser.c b/src/others/xml/parsers/lv_xml_image_parser.c index 4cb9af2444..69215b3864 100644 --- a/src/others/xml/parsers/lv_xml_image_parser.c +++ b/src/others/xml/parsers/lv_xml_image_parser.c @@ -61,12 +61,21 @@ void lv_xml_image_apply(lv_xml_parser_state_t * state, const char ** attrs) const char * value = attrs[i + 1]; if(lv_streq("src", name)) lv_image_set_src(item, lv_xml_get_image(&state->scope, value)); - if(lv_streq("inner_align", name)) lv_image_set_inner_align(item, image_align_to_enum(value)); - if(lv_streq("rotation", name)) lv_image_set_rotation(item, lv_xml_atoi(value)); - if(lv_streq("scale_x", name)) lv_image_set_scale_x(item, lv_xml_atoi(value)); - if(lv_streq("scale_y", name)) lv_image_set_scale_y(item, lv_xml_atoi(value)); - if(lv_streq("pivot_x", name)) lv_image_set_pivot_x(item, lv_xml_to_size(value)); - if(lv_streq("pivot_y", name)) lv_image_set_pivot_y(item, lv_xml_to_size(value)); + else if(lv_streq("inner_align", name)) lv_image_set_inner_align(item, image_align_to_enum(value)); + else if(lv_streq("rotation", name)) lv_image_set_rotation(item, lv_xml_atoi(value)); + else if(lv_streq("scale_x", name)) lv_image_set_scale_x(item, lv_xml_atoi(value)); + else if(lv_streq("scale_y", name)) lv_image_set_scale_y(item, lv_xml_atoi(value)); + else if(lv_streq("pivot_x", name)) lv_image_set_pivot_x(item, lv_xml_to_size(value)); + else if(lv_streq("pivot_y", name)) lv_image_set_pivot_y(item, lv_xml_to_size(value)); + else if(lv_streq("bind_src", name)) { + lv_subject_t * subject = lv_xml_get_subject(&state->scope, value); + if(subject) { + lv_image_bind_src(item, subject); + } + else { + LV_LOG_WARN("Subject \"%s\" doesn't exist in image bind_src", value); + } + } } } diff --git a/src/widgets/image/lv_image.c b/src/widgets/image/lv_image.c index 7a4bc3894e..8b794c54b9 100644 --- a/src/widgets/image/lv_image.c +++ b/src/widgets/image/lv_image.c @@ -13,8 +13,9 @@ #include "../../draw/lv_draw_private.h" #include "../../core/lv_obj_event_private.h" #include "../../core/lv_obj_class_private.h" -#include "../../core/lv_obj_class_private.h" #include "../../core/lv_obj_draw_private.h" +#include "../../core/lv_obj_class_private.h" +#include "../../others/observer/lv_observer_private.h" #if LV_USE_IMAGE != 0 @@ -39,6 +40,11 @@ static void draw_image(lv_event_t * e); static void scale_update(lv_obj_t * obj, int32_t scale_x, int32_t scale_y); static void update_align(lv_obj_t * obj); static void reset_image_attributes(lv_obj_t * obj); + +#if LV_USE_OBSERVER + static void image_src_observer_cb(lv_observer_t * observer, lv_subject_t * subject); +#endif /*LV_USE_OBSERVER*/ + #if LV_USE_OBJ_PROPERTY static void lv_image_set_pivot_helper(lv_obj_t * obj, lv_point_t * pivot); static lv_point_t lv_image_get_pivot_helper(lv_obj_t * obj); @@ -653,6 +659,24 @@ const lv_image_dsc_t * lv_image_get_bitmap_map_src(lv_obj_t * obj) return img->bitmap_mask_src; } + +#if LV_USE_OBSERVER +lv_observer_t * lv_image_bind_src(lv_obj_t * obj, lv_subject_t * subject) +{ + LV_ASSERT_NULL(subject); + LV_ASSERT_OBJ(obj, MY_CLASS); + + if(subject->type != LV_SUBJECT_TYPE_POINTER) { + LV_LOG_WARN("Incompatible subject type: %d", subject->type); + return NULL; + } + + lv_observer_t * observer = lv_subject_add_observer_obj(subject, image_src_observer_cb, obj, NULL); + return observer; +} +#endif /*LV_USE_OBSERVER*/ + + /********************** * STATIC FUNCTIONS **********************/ @@ -1035,6 +1059,18 @@ static void reset_image_attributes(lv_obj_t * obj) lv_obj_refresh_self_size(obj); } + +#if LV_USE_OBSERVER + +static void image_src_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + if(subject->type == LV_SUBJECT_TYPE_POINTER) { + lv_image_set_src(observer->target, subject->value.pointer); + } +} + +#endif /*LV_USE_OBSERVER*/ + #if LV_USE_OBJ_PROPERTY static void lv_image_set_pivot_helper(lv_obj_t * obj, lv_point_t * pivot) { @@ -1049,4 +1085,5 @@ static lv_point_t lv_image_get_pivot_helper(lv_obj_t * obj) } #endif + #endif diff --git a/src/widgets/image/lv_image.h b/src/widgets/image/lv_image.h index bbffbbd8d1..cc2902ce30 100644 --- a/src/widgets/image/lv_image.h +++ b/src/widgets/image/lv_image.h @@ -25,6 +25,7 @@ extern "C" { #include "../../core/lv_obj.h" #include "../../misc/lv_fs.h" #include "../../draw/lv_draw.h" +#include "../../others/observer/lv_observer.h" /********************* * DEFINES @@ -338,6 +339,17 @@ lv_image_align_t lv_image_get_inner_align(lv_obj_t * obj); */ const lv_image_dsc_t * lv_image_get_bitmap_map_src(lv_obj_t * obj); + +#if LV_USE_OBSERVER +/** + * Bind a pointer Subject to an Image's source. + * @param obj pointer to Image + * @param subject pointer to Subject + * @return pointer to newly-created Observer + */ +lv_observer_t * lv_image_bind_src(lv_obj_t * obj, lv_subject_t * subject); +#endif + /********************** * MACROS **********************/ diff --git a/xmls/lv_image.xml b/xmls/lv_image.xml index e154e3e5ed..cd84dadf90 100644 --- a/xmls/lv_image.xml +++ b/xmls/lv_image.xml @@ -29,5 +29,6 @@ Example + \ No newline at end of file