diff --git a/examples/widgets/lv_example_widgets.h b/examples/widgets/lv_example_widgets.h index e397b637f..8b4848d17 100644 --- a/examples/widgets/lv_example_widgets.h +++ b/examples/widgets/lv_example_widgets.h @@ -122,6 +122,7 @@ void lv_example_scale_3(void); void lv_example_scale_4(void); void lv_example_scale_5(void); void lv_example_scale_6(void); +void lv_example_scale_7(void); void lv_example_slider_1(void); void lv_example_slider_2(void); diff --git a/examples/widgets/scale/index.rst b/examples/widgets/scale/index.rst index e9bfa5a5a..69c573303 100644 --- a/examples/widgets/scale/index.rst +++ b/examples/widgets/scale/index.rst @@ -34,3 +34,9 @@ A round scale with multiple needles, resembling a clock .. lv_example:: widgets/scale/lv_example_scale_6 :language: c +Customizing scale major tick label color with `LV_EVENT_DRAW_TASK_ADDED` event +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +.. lv_example:: widgets/scale/lv_example_scale_7 + :language: c + diff --git a/examples/widgets/scale/lv_example_scale_7.c b/examples/widgets/scale/lv_example_scale_7.c new file mode 100644 index 000000000..7891164aa --- /dev/null +++ b/examples/widgets/scale/lv_example_scale_7.c @@ -0,0 +1,72 @@ +#include "../../lv_examples.h" +#if LV_USE_SCALE && LV_BUILD_EXAMPLES + +#include "../../../src/lvgl_private.h" //To expose the fields of lv_draw_task_t + +static void draw_event_cb(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target(e); + lv_draw_task_t * draw_task = lv_event_get_draw_task(e); + lv_draw_dsc_base_t * base_dsc = lv_draw_task_get_draw_dsc(draw_task); + lv_draw_label_dsc_t * label_draw_dsc = lv_draw_task_get_label_dsc(draw_task); + if(base_dsc->part == LV_PART_INDICATOR) { + if(label_draw_dsc) { + const lv_color_t color_idx[7] = { + lv_palette_main(LV_PALETTE_RED), + lv_palette_main(LV_PALETTE_ORANGE), + lv_palette_main(LV_PALETTE_YELLOW), + lv_palette_main(LV_PALETTE_GREEN), + lv_palette_main(LV_PALETTE_CYAN), + lv_palette_main(LV_PALETTE_BLUE), + lv_palette_main(LV_PALETTE_PURPLE), + }; + uint8_t major_tick = lv_scale_get_major_tick_every(obj); + label_draw_dsc->color = color_idx[base_dsc->id1 / major_tick]; + + /*Free the previously allocated text if needed*/ + if(label_draw_dsc->text_local) lv_free((void *)label_draw_dsc->text); + + /*Malloc the text and set text_local as 1 to make LVGL automatically free the text. + * (Local texts are malloc'd internally by LVGL. Mimic this behavior here too)*/ + char tmp_buffer[20] = {0}; /* Big enough buffer */ + lv_snprintf(tmp_buffer, sizeof(tmp_buffer), "%.1f", base_dsc->id2 * 1.0f); + label_draw_dsc->text = lv_strdup(tmp_buffer); + label_draw_dsc->text_local = 1; + + lv_point_t size; + lv_text_get_size(&size, label_draw_dsc->text, label_draw_dsc->font, 0, 0, 1000, LV_TEXT_FLAG_NONE); + int32_t new_w = size.x; + int32_t old_w = lv_area_get_width(&draw_task->area); + + /* Distribute the new size equally on both sides */ + draw_task->area.x1 -= (new_w - old_w) / 2; + draw_task->area.x2 += ((new_w - old_w) + 1) / 2; /* +1 for rounding */ + + } + } +} + +/** + * Customizing scale major tick label color with `LV_EVENT_DRAW_TASK_ADDED` event + */ +void lv_example_scale_7(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + lv_obj_set_size(scale, lv_pct(80), 100); + lv_scale_set_mode(scale, LV_SCALE_MODE_HORIZONTAL_BOTTOM); + lv_obj_center(scale); + + lv_scale_set_label_show(scale, true); + + lv_scale_set_total_tick_count(scale, 31); + lv_scale_set_major_tick_every(scale, 5); + + lv_obj_set_style_length(scale, 5, LV_PART_ITEMS); + lv_obj_set_style_length(scale, 10, LV_PART_INDICATOR); + lv_scale_set_range(scale, 10, 40); + + lv_obj_add_event_cb(scale, draw_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL); + lv_obj_add_flag(scale, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS); +} + +#endif diff --git a/src/widgets/scale/lv_scale.c b/src/widgets/scale/lv_scale.c index 9663e4f54..fbab46018 100644 --- a/src/widgets/scale/lv_scale.c +++ b/src/widgets/scale/lv_scale.c @@ -568,6 +568,9 @@ static void scale_draw_indicator(lv_obj_t * obj, lv_event_t * event) const int32_t tick_value = lv_map(tick_idx, 0U, total_tick_count - 1, scale->range_min, scale->range_max); + label_dsc.base.id1 = tick_idx; + label_dsc.base.id2 = tick_value; + /* Overwrite label and tick properties if tick value is within section range */ lv_scale_section_t * section; LV_LL_READ_BACK(&scale->section_ll, section) { diff --git a/tests/ref_imgs/scale_1.png b/tests/ref_imgs/widgets/scale_1.png similarity index 100% rename from tests/ref_imgs/scale_1.png rename to tests/ref_imgs/widgets/scale_1.png diff --git a/tests/ref_imgs/scale_2.png b/tests/ref_imgs/widgets/scale_2.png similarity index 100% rename from tests/ref_imgs/scale_2.png rename to tests/ref_imgs/widgets/scale_2.png diff --git a/tests/ref_imgs/scale_3.png b/tests/ref_imgs/widgets/scale_3.png similarity index 100% rename from tests/ref_imgs/scale_3.png rename to tests/ref_imgs/widgets/scale_3.png diff --git a/tests/ref_imgs/scale_4.png b/tests/ref_imgs/widgets/scale_4.png similarity index 100% rename from tests/ref_imgs/scale_4.png rename to tests/ref_imgs/widgets/scale_4.png diff --git a/tests/ref_imgs/widgets/scale_5.png b/tests/ref_imgs/widgets/scale_5.png new file mode 100644 index 000000000..13d2b6130 Binary files /dev/null and b/tests/ref_imgs/widgets/scale_5.png differ diff --git a/tests/ref_imgs_vg_lite/scale_1.png b/tests/ref_imgs_vg_lite/widgets/scale_1.png similarity index 100% rename from tests/ref_imgs_vg_lite/scale_1.png rename to tests/ref_imgs_vg_lite/widgets/scale_1.png diff --git a/tests/ref_imgs_vg_lite/scale_2.png b/tests/ref_imgs_vg_lite/widgets/scale_2.png similarity index 100% rename from tests/ref_imgs_vg_lite/scale_2.png rename to tests/ref_imgs_vg_lite/widgets/scale_2.png diff --git a/tests/ref_imgs_vg_lite/scale_3.png b/tests/ref_imgs_vg_lite/widgets/scale_3.png similarity index 100% rename from tests/ref_imgs_vg_lite/scale_3.png rename to tests/ref_imgs_vg_lite/widgets/scale_3.png diff --git a/tests/ref_imgs_vg_lite/scale_4.png b/tests/ref_imgs_vg_lite/widgets/scale_4.png similarity index 100% rename from tests/ref_imgs_vg_lite/scale_4.png rename to tests/ref_imgs_vg_lite/widgets/scale_4.png diff --git a/tests/ref_imgs_vg_lite/widgets/scale_5.png b/tests/ref_imgs_vg_lite/widgets/scale_5.png new file mode 100644 index 000000000..bdd465b62 Binary files /dev/null and b/tests/ref_imgs_vg_lite/widgets/scale_5.png differ diff --git a/tests/src/test_cases/widgets/test_scale.c b/tests/src/test_cases/widgets/test_scale.c index aa3425bab..05ee4f577 100644 --- a/tests/src/test_cases/widgets/test_scale.c +++ b/tests/src/test_cases/widgets/test_scale.c @@ -32,7 +32,7 @@ void test_scale_render_example_1(void) lv_obj_set_style_length(scale, 10, LV_PART_INDICATOR); lv_scale_set_range(scale, 10, 40); - TEST_ASSERT_EQUAL_SCREENSHOT("scale_1.png"); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/scale_1.png"); } /* An vertical scale with section and custom styling */ @@ -117,7 +117,7 @@ void test_scale_render_example_2(void) lv_obj_set_style_radius(scale, 8, 0); lv_obj_set_style_pad_ver(scale, 20, 0); - TEST_ASSERT_EQUAL_SCREENSHOT("scale_2.png"); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/scale_2.png"); } /* A simple round scale */ @@ -140,7 +140,7 @@ void test_scale_render_example_3(void) lv_obj_set_style_length(scale, 10, LV_PART_INDICATOR); lv_scale_set_range(scale, 10, 40); - TEST_ASSERT_EQUAL_SCREENSHOT("scale_3.png"); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/scale_3.png"); } /* A round scale with section and custom styling */ @@ -219,7 +219,72 @@ void test_scale_render_example_4(void) lv_scale_section_set_style(section, LV_PART_ITEMS, §ion_minor_tick_style); lv_scale_section_set_style(section, LV_PART_MAIN, §ion_main_line_style); - TEST_ASSERT_EQUAL_SCREENSHOT("scale_4.png"); + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/scale_4.png"); +} + +static void draw_event_cb(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target(e); + lv_draw_task_t * draw_task = lv_event_get_draw_task(e); + lv_draw_dsc_base_t * base_dsc = lv_draw_task_get_draw_dsc(draw_task); + lv_draw_label_dsc_t * label_draw_dsc = lv_draw_task_get_label_dsc(draw_task); + if(base_dsc->part == LV_PART_INDICATOR) { + if(label_draw_dsc) { + const lv_color_t color_idx[7] = { + lv_palette_main(LV_PALETTE_RED), + lv_palette_main(LV_PALETTE_ORANGE), + lv_palette_main(LV_PALETTE_YELLOW), + lv_palette_main(LV_PALETTE_GREEN), + lv_palette_main(LV_PALETTE_CYAN), + lv_palette_main(LV_PALETTE_BLUE), + lv_palette_main(LV_PALETTE_PURPLE), + }; + uint8_t major_tick = lv_scale_get_major_tick_every(obj); + label_draw_dsc->color = color_idx[base_dsc->id1 / major_tick]; + + /*Free the previously allocated text if needed*/ + if(label_draw_dsc->text_local) lv_free((void *)label_draw_dsc->text); + + /*Malloc the text and set text_local as 1 to make LVGL automatically free the text. + * (Local texts are malloc'd internally by LVGL. Mimic this behavior here too)*/ + char tmp_buffer[20] = {0}; /* Big enough buffer */ + lv_snprintf(tmp_buffer, sizeof(tmp_buffer), "%.1f", base_dsc->id2 * 1.0f); + label_draw_dsc->text = lv_strdup(tmp_buffer); + label_draw_dsc->text_local = 1; + + lv_point_t size; + lv_text_get_size(&size, label_draw_dsc->text, label_draw_dsc->font, 0, 0, 1000, LV_TEXT_FLAG_NONE); + int32_t new_w = size.x; + int32_t old_w = lv_area_get_width(&draw_task->area); + + /* Distribute the new size equally on both sides */ + draw_task->area.x1 -= (new_w - old_w) / 2; + draw_task->area.x2 += ((new_w - old_w) + 1) / 2; /* +1 for rounding */ + + } + } +} + +void test_scale_render_example_7(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + lv_obj_set_size(scale, lv_pct(80), 100); + lv_scale_set_mode(scale, LV_SCALE_MODE_HORIZONTAL_BOTTOM); + lv_obj_center(scale); + + lv_scale_set_label_show(scale, true); + + lv_scale_set_total_tick_count(scale, 31); + lv_scale_set_major_tick_every(scale, 5); + + lv_obj_set_style_length(scale, 5, LV_PART_ITEMS); + lv_obj_set_style_length(scale, 10, LV_PART_INDICATOR); + lv_scale_set_range(scale, 10, 40); + + lv_obj_add_event_cb(scale, draw_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL); + lv_obj_add_flag(scale, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS); + + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/scale_5.png"); } void test_scale_set_style(void)