mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-30 07:06:19 +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 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
|
#if LV_USE_OBSERVER
|
||||||
static void scale_section_min_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
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_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;
|
needle_line_points[1].y = scale_height / 2 + needle_length_y;
|
||||||
|
|
||||||
lv_line_set_points_mutable(needle_line, needle_line_points, 2);
|
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)
|
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);
|
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[])
|
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->draw_ticks_on_top = false;
|
||||||
scale->custom_label_cnt = 0;
|
scale->custom_label_cnt = 0;
|
||||||
scale->txt_src = NULL;
|
scale->txt_src = NULL;
|
||||||
|
lv_array_init(&scale->needles, 0, sizeof(lv_scale_needle_t));
|
||||||
|
|
||||||
lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
|
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);
|
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");
|
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 */
|
/* NOTE: Extend scale draw size so the first tick label can be shown */
|
||||||
lv_event_set_ext_draw_size(event, 100);
|
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 {
|
else {
|
||||||
/* Nothing to do. Invalid event */
|
/* 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;
|
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
|
#if LV_USE_OBSERVER
|
||||||
|
|
||||||
static void scale_section_min_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
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
|
uint32_t last_tick_idx_is_major : 1; /**< Internal (set during drawing): true if
|
||||||
* `last_tick_idx_in_section` represents a major tick. */
|
* `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 {
|
struct _lv_scale_t {
|
||||||
lv_obj_t obj; /**< Base Widget part of Scale */
|
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 custom_label_cnt; /**< Number of custom labels provided in `txt_src` */
|
||||||
int32_t last_tick_width; /**< Width of last tick in pixels */
|
int32_t last_tick_width; /**< Width of last tick in pixels */
|
||||||
int32_t first_tick_width; /**< Width of first 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}>
|
$<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
|
add_library(test_common
|
||||||
STATIC
|
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
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user