feat(scale): add observer binding functions for line and image needle… (#9838)
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify GDB constants are up-to-date / verify-gdb-consts (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled

This commit is contained in:
Sven
2026-03-19 05:59:57 +00:00
committed by GitHub
parent cd07338461
commit 5100d33bb7
4 changed files with 167 additions and 0 deletions
+38
View File
@@ -283,6 +283,44 @@ The Style properties that are used during Scale drawing (and are thus useful) ar
:LV_STYLE_TEXT_FONT: :cpp:func:`lv_style_set_text_font`
.. _lv_scale_needles:
Needles
-------
Needles are used to indicate a specific value for ``..._ROUND_...`` Scales only.
They can be lines or images and can be customized in terms of length, color, and
other properties.
.. _lv_scale_creating_needles:
Creating Needles
~~~~~~~~~~~~~~~~
Create a :ref:`lv_line <lv_line>` or a :ref:`lv_image <lv_image>` Widget and then
attach it to the Scale as a needle with the appropriate function:
- :cpp:expr:`lv_scale_set_line_needle_value(scale, needle_line, needle_length, value)`
- :cpp:expr:`lv_scale_set_image_needle_value(scale, needle_img, value)`
Data binding
~~~~~~~~~~~~
To get familiar with observers, subjects, and data bindings in general, visit the
:ref:`Observer <observer_how_to_use>` page.
This method of subscribing to an integer Subject affects the needle value of a Scale
Widget directly. Note that this is a one-way binding (Subject ==> Widget) so when
the subject changes, the Scale's needle will be updated too.
It supports only integer subjects.
- :cpp:expr:`lv_scale_bind_line_needle_value(scale, needle_line, needle_length, &subject)`
- :cpp:expr:`lv_scale_bind_image_needle_value(scale, needle_img, &subject)`
.. _lv_scale_events:
+70
View File
@@ -32,6 +32,12 @@
/**********************
* TYPEDEFS
**********************/
#if LV_USE_OBSERVER
typedef struct {
lv_obj_t * needle_line;
int32_t needle_length;
} bind_element_needle_t;
#endif
/**********************
* STATIC PROTOTYPES
@@ -77,6 +83,8 @@ static void needle_deleted_cb(lv_event_t * e);
#if LV_USE_OBSERVER
static void scale_section_min_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
static void scale_section_max_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
static void scale_line_needle_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
static void scale_image_needle_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif /*LV_USE_OBSERVER*/
/**********************
@@ -609,6 +617,55 @@ lv_observer_t * lv_scale_bind_section_max_value(lv_obj_t * obj, lv_scale_section
return observer;
}
lv_observer_t * lv_scale_bind_line_needle_value(lv_obj_t * obj, lv_obj_t * needle_line, int32_t needle_length,
lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_OBJ(obj, MY_CLASS);
LV_ASSERT_NULL(needle_line);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
bind_element_needle_t * user_data = lv_zalloc(sizeof(bind_element_needle_t));
if(user_data == NULL) {
LV_LOG_WARN("Couldn't allocate user_data");
LV_ASSERT_MALLOC(user_data);
return NULL;
}
user_data->needle_line = needle_line;
user_data->needle_length = needle_length;
lv_observer_t * observer = lv_subject_add_observer_obj(subject, scale_line_needle_value_observer_cb, obj, user_data);
if(observer == NULL) {
LV_LOG_WARN("Couldn't create observer");
lv_free(user_data);
return NULL;
}
observer->auto_free_user_data = 1;
return observer;
}
lv_observer_t * lv_scale_bind_image_needle_value(lv_obj_t * obj, lv_obj_t * needle_img, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_OBJ(obj, MY_CLASS);
LV_ASSERT_NULL(needle_img);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_observer_t * observer = lv_subject_add_observer_obj(subject, scale_image_needle_value_observer_cb, obj, needle_img);
return observer;
}
#endif /*LV_USE_OBSERVER*/
/**********************
@@ -1887,6 +1944,19 @@ static void scale_section_max_value_observer_cb(lv_observer_t * observer, lv_sub
lv_scale_set_section_max_value(observer->target, section, subject->value.num);
}
static void scale_line_needle_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
bind_element_needle_t * bind_element = observer->user_data;
lv_scale_set_line_needle_value(observer->target, bind_element->needle_line, bind_element->needle_length,
subject->value.num);
}
static void scale_image_needle_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
lv_obj_t * needle_img = observer->user_data;
lv_scale_set_image_needle_value(observer->target, needle_img, subject->value.num);
}
#endif /*LV_USE_OBSERVER*/
+20
View File
@@ -383,6 +383,26 @@ lv_observer_t * lv_scale_bind_section_min_value(lv_obj_t * obj, lv_scale_section
*/
lv_observer_t * lv_scale_bind_section_max_value(lv_obj_t * obj, lv_scale_section_t * section, lv_subject_t * subject);
/**
* Bind an integer subject to a scale's line needle value
* @param obj pointer to a Scale
* @param needle_line pointer to a line needle
* @param needle_length length of the needle
* @param subject pointer to a Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_scale_bind_line_needle_value(lv_obj_t * obj, lv_obj_t * needle_line, int32_t needle_length,
lv_subject_t * subject);
/**
* Bind an integer subject to a scale's image needle value
* @param obj pointer to a Scale
* @param needle_img pointer to an image needle
* @param subject pointer to a Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_scale_bind_image_needle_value(lv_obj_t * obj, lv_obj_t * needle_img, lv_subject_t * subject);
#endif
/**********************
+39
View File
@@ -996,6 +996,45 @@ void test_observer_dropdown_value(void)
TEST_ASSERT_EQUAL(0, lv_subject_get_int(&subject));
}
void test_observer_scale_line_needle_value(void)
{
lv_obj_t * obj = lv_scale_create(lv_screen_active());
lv_scale_set_mode(obj, LV_SCALE_MODE_ROUND_INNER);
lv_scale_t * scale = (lv_scale_t *)obj;
lv_obj_t * needle = lv_line_create(obj);
static lv_subject_t subject;
lv_subject_init_int(&subject, 30);
lv_scale_bind_line_needle_value(obj, needle, 50, &subject);
lv_scale_needle_t * scale_needle = lv_array_at(&scale->needles, 0);
TEST_ASSERT_EQUAL(30, scale_needle->value);
TEST_ASSERT_EQUAL(50, scale_needle->length);
lv_subject_set_int(&subject, 40);
TEST_ASSERT_EQUAL(40, scale_needle->value);
}
void test_observer_scale_image_needle_value(void)
{
lv_obj_t * obj = lv_scale_create(lv_screen_active());
lv_scale_set_mode(obj, LV_SCALE_MODE_ROUND_INNER);
lv_scale_t * scale = (lv_scale_t *)obj;
lv_obj_t * needle = lv_image_create(obj);
static lv_subject_t subject;
lv_subject_init_int(&subject, 30);
lv_scale_bind_image_needle_value(obj, needle, &subject);
lv_scale_needle_t * scale_needle = lv_array_at(&scale->needles, 0);
TEST_ASSERT_EQUAL(30, scale_needle->value);
lv_subject_set_int(&subject, 40);
TEST_ASSERT_EQUAL(40, scale_needle->value);
}
void test_observer_deinit(void)
{
static lv_subject_t subject;