From f8c26ea150189d26bcd0c0cd98d45bf615ed692f Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 7 Jul 2024 06:30:55 +0200 Subject: [PATCH] feat(observer): add lv_obj_remove_from_subject (#6341) --- docs/others/observer.rst | 7 ++--- src/others/observer/lv_observer.c | 40 +++++++++------------------- src/others/observer/lv_observer.h | 9 ++++--- tests/src/test_cases/test_observer.c | 10 +++---- 4 files changed, 26 insertions(+), 40 deletions(-) diff --git a/docs/others/observer.rst b/docs/others/observer.rst index 3204db2876..0113ca7f7f 100644 --- a/docs/others/observer.rst +++ b/docs/others/observer.rst @@ -171,13 +171,14 @@ Unsubscribe from a subject .. code:: c - lv_observer_remove(observer) + //`observer` is the return value of `lv_subject_add_observer*` + lv_observer_remove(observer); -To unsubscribe from a subject with all widgets you can use: +To unsubscribe a widget from a given or all subject use: .. code:: c - lv_subject_remove_obj(subject, obj) + lv_obj_remove_from_subject(obj, subject); //`subject` can be NULL to unsubcribe from all .. _observer_subject_groups: diff --git a/src/others/observer/lv_observer.c b/src/others/observer/lv_observer.c index b132914985..ced3378804 100644 --- a/src/others/observer/lv_observer.c +++ b/src/others/observer/lv_observer.c @@ -356,6 +356,7 @@ lv_observer_t * lv_subject_add_observer_with_target(lv_subject_t * subject, lv_o return observer; } + void lv_observer_remove(lv_observer_t * observer) { LV_ASSERT_NULL(observer); @@ -370,36 +371,19 @@ void lv_observer_remove(lv_observer_t * observer) lv_free(observer); } -void lv_subject_remove_all_obj(lv_subject_t * subject, lv_obj_t * obj) +void lv_obj_remove_from_subject(lv_obj_t * obj, lv_subject_t * subject) { - LV_ASSERT_NULL(subject); - if(subject->type == LV_SUBJECT_TYPE_INVALID) { - LV_LOG_WARN("Subject not initialized yet"); - return; - } - - while(lv_obj_remove_event_cb(obj, unsubscribe_on_delete_cb)); - while(lv_obj_remove_event_cb(obj, obj_value_changed_event_cb)); - -#if LV_USE_ARC - while(lv_obj_remove_event_cb(obj, arc_value_changed_event_cb)); -#endif /*LV_USE_ARC*/ - -#if LV_USE_ROLLER - while(lv_obj_remove_event_cb(obj, roller_value_changed_event_cb)); -#endif /*LV_USE_ROLLER*/ - -#if LV_USE_DROPDOWN - while(lv_obj_remove_event_cb(obj, dropdown_value_changed_event_cb)); -#endif /*LV_USE_DROPDOWN*/ - - lv_observer_t * observer = _lv_ll_get_head(&subject->subs_ll); - while(observer) { - lv_observer_t * observer_next = _lv_ll_get_next(&subject->subs_ll, observer); - if(observer->target == obj) { - lv_observer_remove(observer); + int32_t i; + int32_t event_cnt = (int32_t)(obj->spec_attr ? lv_array_size(&obj->spec_attr->event_list) : 0); + for(i = event_cnt - 1; i >= 0; i--) { + lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(obj, i); + if(event_dsc->cb == unsubscribe_on_delete_cb) { + lv_observer_t * observer = event_dsc->user_data; + if(subject == NULL || subject == observer->subject) { + lv_observer_remove(observer); + lv_obj_remove_event(obj, i); + } } - observer = observer_next; } } diff --git a/src/others/observer/lv_observer.h b/src/others/observer/lv_observer.h index 7ef19cb147..f7d5389653 100644 --- a/src/others/observer/lv_observer.h +++ b/src/others/observer/lv_observer.h @@ -265,11 +265,12 @@ lv_observer_t * lv_subject_add_observer_with_target(lv_subject_t * subject, lv_o void lv_observer_remove(lv_observer_t * observer); /** - * Remove all observers from their subject related to an object - * @param observer pointer to an observer - * @param obj pointer to an object + * Remove the observers of an object from a subject or all subjects + * @param obj the object whose observers should be removed + * @param subject the subject to remove the object from, or `NULL` to remove from all subjects + * @note This function can be used e.g. when an object's subject(s) needs to be replaced by other subject(s) */ -void lv_subject_remove_all_obj(lv_subject_t * subject, lv_obj_t * obj); +void lv_obj_remove_from_subject(lv_obj_t * obj, lv_subject_t * subject); /** * Get the target of an observer diff --git a/tests/src/test_cases/test_observer.c b/tests/src/test_cases/test_observer.c index fa94ea1dc1..3de18609db 100644 --- a/tests/src/test_cases/test_observer.c +++ b/tests/src/test_cases/test_observer.c @@ -332,7 +332,7 @@ void test_observer_label_text_normal(void) TEST_ASSERT_EQUAL_STRING("world", lv_label_get_text(obj)); /*Remove the label from the subject*/ - lv_subject_remove_all_obj(&subject_string, obj); + lv_obj_remove_from_subject(obj, &subject_string); lv_subject_copy_string(&subject_string, "nothing"); TEST_ASSERT_EQUAL_STRING("world", lv_label_get_text(obj)); @@ -346,7 +346,7 @@ void test_observer_label_text_normal(void) TEST_ASSERT_EQUAL_STRING("WORLD", lv_label_get_text(obj)); /*Remove the label from the subject*/ - lv_subject_remove_all_obj(&subject_pointer, obj); + lv_obj_remove_from_subject(obj, &subject_pointer); lv_subject_copy_string(&subject_pointer, "NOTHING"); TEST_ASSERT_EQUAL_STRING("WORLD", lv_label_get_text(obj)); } @@ -373,7 +373,7 @@ void test_observer_label_text_formatted(void) TEST_ASSERT_EQUAL_STRING("value: -20", lv_label_get_text(obj)); /*Remove the label from the subject*/ - lv_subject_remove_all_obj(&subject_int, obj); + lv_obj_remove_from_subject(obj, &subject_int); lv_subject_set_int(&subject_int, 100); TEST_ASSERT_EQUAL_STRING("value: -20", lv_label_get_text(obj)); @@ -388,7 +388,7 @@ void test_observer_label_text_formatted(void) TEST_ASSERT_EQUAL_STRING("text: world", lv_label_get_text(obj)); /*Remove the label from the subject*/ - lv_subject_remove_all_obj(&subject_string, obj); + lv_obj_remove_from_subject(obj, &subject_string); lv_subject_copy_string(&subject_string, "nothing"); TEST_ASSERT_EQUAL_STRING("text: world", lv_label_get_text(obj)); @@ -402,7 +402,7 @@ void test_observer_label_text_formatted(void) TEST_ASSERT_EQUAL_STRING("pointer: WORLD", lv_label_get_text(obj)); /*Remove the label from the subject*/ - lv_subject_remove_all_obj(&subject_pointer, obj); + lv_obj_remove_from_subject(obj, &subject_pointer); lv_subject_copy_string(&subject_pointer, "NOTHING"); TEST_ASSERT_EQUAL_STRING("pointer: WORLD", lv_label_get_text(obj)); }