mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-24 08:16:29 +08:00
feat(scale): update needles when scale is transformed (#9340)
This commit is contained in:
@@ -71,6 +71,9 @@ static void scale_free_line_needle_points_cb(lv_event_t * e);
|
||||
|
||||
static bool scale_is_major_tick(lv_scale_t * scale, uint32_t tick_idx);
|
||||
|
||||
static lv_result_t update_needle(lv_scale_t * scale, lv_obj_t * needle, int32_t length, int32_t value);
|
||||
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);
|
||||
@@ -297,6 +300,8 @@ void lv_scale_set_line_needle_value(lv_obj_t * obj, lv_obj_t * needle_line, int3
|
||||
needle_line_points[1].y = scale_height / 2 + needle_length_y;
|
||||
|
||||
lv_line_set_points_mutable(needle_line, needle_line_points, 2);
|
||||
|
||||
update_needle(scale, needle_line, needle_length, value);
|
||||
}
|
||||
|
||||
void lv_scale_set_image_needle_value(lv_obj_t * obj, lv_obj_t * needle_img, int32_t value)
|
||||
@@ -320,6 +325,7 @@ void lv_scale_set_image_needle_value(lv_obj_t * obj, lv_obj_t * needle_img, int3
|
||||
}
|
||||
|
||||
lv_image_set_rotation(needle_img, (scale->rotation + angle) * 10);
|
||||
update_needle(scale, needle_img, 0, value);
|
||||
}
|
||||
|
||||
void lv_scale_set_text_src(lv_obj_t * obj, const char * txt_src[])
|
||||
@@ -586,6 +592,7 @@ static void lv_scale_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
scale->draw_ticks_on_top = false;
|
||||
scale->custom_label_cnt = 0;
|
||||
scale->txt_src = NULL;
|
||||
lv_array_init(&scale->needles, 0, sizeof(lv_scale_needle_t));
|
||||
|
||||
lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
@@ -606,6 +613,13 @@ static void lv_scale_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
}
|
||||
lv_ll_clear(&scale->section_ll);
|
||||
|
||||
size_t needle_count = lv_array_size(&scale->needles);
|
||||
for(size_t i = 0; i < needle_count; ++i) {
|
||||
lv_scale_needle_t * scale_needle = lv_array_at(&scale->needles, i);
|
||||
lv_obj_remove_event_cb(scale_needle->obj, needle_deleted_cb);
|
||||
}
|
||||
lv_array_deinit(&scale->needles);
|
||||
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
}
|
||||
|
||||
@@ -656,6 +670,18 @@ static void lv_scale_event(const lv_obj_class_t * class_p, lv_event_t * event)
|
||||
/* NOTE: Extend scale draw size so the first tick label can be shown */
|
||||
lv_event_set_ext_draw_size(event, 100);
|
||||
}
|
||||
else if(event_code == LV_EVENT_STYLE_CHANGED) {
|
||||
size_t needle_count = lv_array_size(&scale->needles);
|
||||
for(size_t i = 0; i < needle_count; ++i) {
|
||||
lv_scale_needle_t * needle = lv_array_at(&scale->needles, i);
|
||||
if(lv_obj_has_class(needle->obj, &lv_line_class)) {
|
||||
lv_scale_set_line_needle_value(obj, needle->obj, needle->length, needle->value);
|
||||
}
|
||||
else {
|
||||
lv_scale_set_image_needle_value(obj, needle->obj, needle->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Nothing to do. Invalid event */
|
||||
}
|
||||
@@ -1761,6 +1787,46 @@ static bool scale_is_major_tick(lv_scale_t * scale, uint32_t tick_idx)
|
||||
return scale->major_tick_every != 0 && tick_idx % scale->major_tick_every == 0;
|
||||
}
|
||||
|
||||
static lv_result_t update_needle(lv_scale_t * scale, lv_obj_t * needle, int32_t length, int32_t value)
|
||||
{
|
||||
/* First try to find the needle in the haystack (scale's needle list) */
|
||||
size_t needle_count = lv_array_size(&scale->needles);
|
||||
for(size_t i = 0; i < needle_count; ++i) {
|
||||
lv_scale_needle_t * scale_needle = lv_array_at(&scale->needles, i);
|
||||
if(scale_needle->obj == needle) {
|
||||
scale_needle->value = value;
|
||||
scale_needle->length = length;
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Needle is not yet part of the haystack */
|
||||
lv_scale_needle_t scale_needle = {.obj = needle, .length = length, .value = value};
|
||||
lv_result_t res = lv_array_push_back(&scale->needles, &scale_needle);
|
||||
if(res != LV_RESULT_OK) {
|
||||
LV_LOG_WARN("Failed to attach needle to scale - not enough memory");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_obj_add_event_cb(needle, needle_deleted_cb, LV_EVENT_DELETE, scale);
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
static void needle_deleted_cb(lv_event_t * e)
|
||||
{
|
||||
lv_scale_t * scale = lv_event_get_user_data(e);
|
||||
lv_obj_t * needle = lv_event_get_target_obj(e);
|
||||
|
||||
size_t needle_count = lv_array_size(&scale->needles);
|
||||
for(size_t i = 0; i < needle_count; ++i) {
|
||||
lv_scale_needle_t * scale_needle = lv_array_at(&scale->needles, i);
|
||||
if(scale_needle->obj == needle) {
|
||||
lv_array_remove(&scale->needles, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_USE_OBSERVER
|
||||
|
||||
static void scale_section_min_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
|
||||
@@ -55,6 +55,11 @@ struct _lv_scale_section_t {
|
||||
uint32_t last_tick_idx_is_major : 1; /**< Internal (set during drawing): true if
|
||||
* `last_tick_idx_in_section` represents a major tick. */
|
||||
};
|
||||
typedef struct {
|
||||
lv_obj_t * obj;
|
||||
int32_t value;
|
||||
int32_t length;
|
||||
} lv_scale_needle_t;
|
||||
|
||||
struct _lv_scale_t {
|
||||
lv_obj_t obj; /**< Base Widget part of Scale */
|
||||
@@ -77,6 +82,7 @@ struct _lv_scale_t {
|
||||
int32_t custom_label_cnt; /**< Number of custom labels provided in `txt_src` */
|
||||
int32_t last_tick_width; /**< Width of last tick in pixels */
|
||||
int32_t first_tick_width; /**< Width of first tick in pixels */
|
||||
lv_array_t needles; /**< Needle list of this scale */
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -292,7 +292,9 @@ set(TEST_INCLUDE_DIRS
|
||||
$<BUILD_INTERFACE:${LVGL_CONF_DIR}>
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE TEST_IMAGES_SRC ${LVGL_TEST_DIR}/test_images/*.c)
|
||||
file(GLOB_RECURSE TEST_IMAGES_SRC
|
||||
${LVGL_TEST_DIR}/test_images/*.c
|
||||
${LVGL_TEST_DIR}/../examples/assets/*.c)
|
||||
|
||||
add_library(test_common
|
||||
STATIC
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
@@ -542,4 +542,41 @@ void test_scale_set_line_needle_value(void)
|
||||
);
|
||||
}
|
||||
|
||||
void test_scale_needle_updates_when_style_changes(void)
|
||||
{
|
||||
|
||||
lv_obj_t * scale = lv_scale_create(lv_screen_active());
|
||||
|
||||
lv_obj_align(scale, LV_ALIGN_LEFT_MID, 0, 0);
|
||||
lv_obj_set_style_width(scale, 200, LV_PART_MAIN);
|
||||
lv_obj_set_style_height(scale, 200, LV_PART_MAIN);
|
||||
|
||||
lv_scale_set_mode(scale, LV_SCALE_MODE_ROUND_INNER);
|
||||
|
||||
lv_scale_set_range(scale, 0, 100);
|
||||
lv_scale_set_angle_range(scale, 270);
|
||||
lv_scale_set_rotation(scale, 135);
|
||||
|
||||
lv_scale_set_total_tick_count(scale, 20);
|
||||
lv_scale_set_major_tick_every(scale, 5);
|
||||
|
||||
lv_obj_t * needle_line = lv_line_create(scale);
|
||||
lv_obj_set_style_line_width(needle_line, 6, LV_PART_MAIN);
|
||||
lv_obj_set_style_line_rounded(needle_line, true, LV_PART_MAIN);
|
||||
lv_scale_set_line_needle_value(scale, needle_line, 60, 26);
|
||||
|
||||
LV_IMAGE_DECLARE(img_hand);
|
||||
lv_obj_t * needle_img = lv_image_create(scale);
|
||||
lv_image_set_src(needle_img, &img_hand);
|
||||
lv_scale_set_image_needle_value(scale, needle_img, 78);
|
||||
lv_obj_align(needle_img, LV_ALIGN_CENTER, 47, -2);
|
||||
lv_image_set_pivot(needle_img, 3, 4);
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/scale_7.png");
|
||||
|
||||
lv_obj_align(scale, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/scale_8.png");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user