diff --git a/src/widgets/scale/lv_scale.c b/src/widgets/scale/lv_scale.c index f101e6892..c67dc757e 100644 --- a/src/widgets/scale/lv_scale.c +++ b/src/widgets/scale/lv_scale.c @@ -110,7 +110,7 @@ void lv_scale_set_mode(lv_obj_t * obj, lv_scale_mode_t mode) lv_obj_invalidate(obj); } -void lv_scale_set_total_tick_count(lv_obj_t * obj, int32_t total_tick_count) +void lv_scale_set_total_tick_count(lv_obj_t * obj, uint32_t total_tick_count) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_scale_t * scale = (lv_scale_t *)obj; @@ -120,7 +120,7 @@ void lv_scale_set_total_tick_count(lv_obj_t * obj, int32_t total_tick_count) lv_obj_invalidate(obj); } -void lv_scale_set_major_tick_every(lv_obj_t * obj, int32_t major_tick_every) +void lv_scale_set_major_tick_every(lv_obj_t * obj, uint32_t major_tick_every) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_scale_t * scale = (lv_scale_t *)obj; @@ -130,7 +130,7 @@ void lv_scale_set_major_tick_every(lv_obj_t * obj, int32_t major_tick_every) lv_obj_invalidate(obj); } -void lv_scale_set_major_tick_length(lv_obj_t * obj, int32_t major_len) +void lv_scale_set_major_tick_length(lv_obj_t * obj, uint32_t major_len) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_scale_t * scale = (lv_scale_t *)obj; @@ -140,7 +140,7 @@ void lv_scale_set_major_tick_length(lv_obj_t * obj, int32_t major_len) lv_obj_invalidate(obj); } -void lv_scale_set_minor_tick_length(lv_obj_t * obj, int32_t minor_len) +void lv_scale_set_minor_tick_length(lv_obj_t * obj, uint32_t minor_len) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_scale_t * scale = (lv_scale_t *)obj; @@ -357,6 +357,48 @@ void lv_scale_section_set_style(lv_scale_section_t * section, uint32_t part, lv_ * Getter functions *====================*/ +lv_scale_mode_t lv_scale_get_mode(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->mode; +} + +int32_t lv_scale_get_total_tick_count(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->total_tick_count; +} + +int32_t lv_scale_get_major_tick_every(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->major_tick_every; +} + +bool lv_scale_get_label_show(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->label_enabled; +} + +uint32_t lv_scale_get_angle_range(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->angle_range; +} + +int32_t lv_scale_get_range_min_value(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->range_min; +} + +int32_t lv_scale_get_range_max_value(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->range_max; +} + /*===================== * Other functions *====================*/ @@ -907,37 +949,43 @@ static void scale_get_tick_points(lv_obj_t * obj, const uint32_t tick_idx, bool x_ofs = obj->coords.x1 + (pad_right + tick_pad_right); y_ofs = obj->coords.y1 + (main_line_dsc.width / 2U) + pad_top; } - else if(LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode) { + /* LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode */ + else { x_ofs = obj->coords.x1 + (pad_left + tick_pad_left); y_ofs = obj->coords.y2 + (main_line_dsc.width / 2U) - pad_bottom; } - else { /* Nothing to do */ } - if(is_major_tick && ((LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode) || (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode))) { - major_len *= -1; - } - /* Draw tick lines to the right or top */ - else if(!is_major_tick && (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode || - LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode)) { - minor_len *= -1; + /* Adjust length when tick will be drawn on horizontal top or vertical right scales */ + if((LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode) || (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode)) { + if(is_major_tick) { + major_len *= -1; + } + else { + minor_len *= -1; + } } else { /* Nothing to do */ } const int32_t tick_length = is_major_tick ? major_len : minor_len; + /* NOTE + * Minus 1 because tick count starts at 0 + * TODO + * What if total_tick_count is 1? This will lead to an division by 0 further down */ + const uint32_t tmp_tick_count = scale->total_tick_count - 1U; - /* Setup the tick points */ + /* Calculate the position of the tick points based on the mode and tick index */ if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { /* Vertical position starts at y2 of the scale main line, we start at y2 because the ticks are drawn from bottom to top */ int32_t vertical_position = obj->coords.y2 - (pad_bottom + tick_pad_bottom); - if((scale->total_tick_count - 1U) == tick_idx) { + /* Position the last tick */ + if(tmp_tick_count == tick_idx) { vertical_position = y_ofs; } - /* Increment the tick offset depending of its index */ + /* Otherwise adjust the tick position depending of its index and number of ticks on the scale */ else if(0 != tick_idx) { const int32_t scale_total_height = lv_obj_get_height(obj) - (pad_top + pad_bottom + tick_pad_top + tick_pad_bottom); - int32_t offset = ((int32_t) tick_idx * (int32_t) scale_total_height) / (int32_t)( - scale->total_tick_count - 1); + const int32_t offset = ((int32_t) tick_idx * (int32_t) scale_total_height) / (int32_t)(tmp_tick_count); vertical_position -= offset; } else { /* Nothing to do */ } @@ -950,15 +998,15 @@ static void scale_get_tick_points(lv_obj_t * obj, const uint32_t tick_idx, bool else { /* Horizontal position starts at x1 of the scale main line */ int32_t horizontal_position = x_ofs; - /* Position the last tick at the x2 scale coordinate */ - if((scale->total_tick_count - 1U) == tick_idx) { + + /* Position the last tick */ + if(tmp_tick_count == tick_idx) { horizontal_position = obj->coords.x2 - (pad_left + tick_pad_left); } - /* Increment the tick offset depending of its index */ + /* Otherwise adjust the tick position depending of its index and number of ticks on the scale */ else if(0U != tick_idx) { const int32_t scale_total_width = lv_obj_get_width(obj) - (pad_right + pad_left + tick_pad_right + tick_pad_left); - int32_t offset = ((int32_t) tick_idx * (int32_t) scale_total_width) / (int32_t)( - scale->total_tick_count - 1); + const int32_t offset = ((int32_t) tick_idx * (int32_t) scale_total_width) / (int32_t)(tmp_tick_count); horizontal_position += offset; } else { /* Nothing to do */ } @@ -991,11 +1039,11 @@ static void scale_get_tick_points(lv_obj_t * obj, const uint32_t tick_idx, bool point_closer_to_arc = radius_edge - main_line_dsc.width; adjusted_radio_with_tick_len = point_closer_to_arc - (is_major_tick ? major_len : minor_len); } - else if(LV_SCALE_MODE_ROUND_OUTER == scale->mode) { + /* LV_SCALE_MODE_ROUND_OUTER == scale->mode */ + else { point_closer_to_arc = radius_edge - main_line_dsc.width; adjusted_radio_with_tick_len = point_closer_to_arc + (is_major_tick ? major_len : minor_len); } - else { /* Nothing to do */ } tick_point_a->x = center_point.x + point_closer_to_arc; tick_point_a->y = center_point.y; @@ -1271,32 +1319,38 @@ static void scale_store_main_line_tick_width_compensation(lv_obj_t * obj, const const bool is_major_tick, const int32_t major_tick_width, const int32_t minor_tick_width) { lv_scale_t * scale = (lv_scale_t *)obj; + const bool is_first_tick = 0U == tick_idx; + const bool is_last_tick = scale->total_tick_count == tick_idx; + const int32_t tick_width = is_major_tick ? major_tick_width : minor_tick_width; - if(scale->total_tick_count == tick_idx) { - if((LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) || (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode)) { - scale->last_tick_width = is_major_tick ? major_tick_width : minor_tick_width; - } - else if((LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode) || (LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode)) { - scale->first_tick_width = is_major_tick ? major_tick_width : minor_tick_width; - } - else if((LV_SCALE_MODE_ROUND_INNER == scale->mode) || (LV_SCALE_MODE_ROUND_OUTER == scale->mode)) { - /* TODO */ - } - else { /* Nothing to do */ } + /* Exit early if tick_idx is not the first nor last tick on the main line */ + if(((!is_last_tick) && (!is_first_tick)) + /* Exit early if scale mode is round. It doesn't support main line compensation */ + || ((LV_SCALE_MODE_ROUND_INNER == scale->mode) || (LV_SCALE_MODE_ROUND_OUTER == scale->mode))) { + return; } - else if(0U == tick_idx) { + + if(is_last_tick) { + /* Mode is vertical */ if((LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) || (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode)) { - scale->first_tick_width = is_major_tick ? major_tick_width : minor_tick_width; + scale->last_tick_width = tick_width; } - else if((LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode) || (LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode)) { - scale->last_tick_width = is_major_tick ? major_tick_width : minor_tick_width; + /* Mode is horizontal */ + else { + scale->first_tick_width = tick_width; + } + } + /* is_first_tick */ + else { + /* Mode is vertical */ + if((LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) || (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode)) { + scale->first_tick_width = tick_width; + } + /* Mode is horizontal */ + else { + scale->last_tick_width = tick_width; } - else if((LV_SCALE_MODE_ROUND_INNER == scale->mode) || (LV_SCALE_MODE_ROUND_OUTER == scale->mode)) { - /* TODO */ - } - else { /* Nothing to do */ } } - else { /* Nothing to do */ } } /** diff --git a/src/widgets/scale/lv_scale.h b/src/widgets/scale/lv_scale.h index 5004e9eca..34813b03b 100644 --- a/src/widgets/scale/lv_scale.h +++ b/src/widgets/scale/lv_scale.h @@ -75,21 +75,22 @@ typedef struct { lv_obj_t obj; lv_ll_t section_ll; /**< Linked list for the sections (stores lv_scale_section_t)*/ const char ** txt_src; - int32_t custom_label_cnt; - int32_t major_len; - int32_t minor_len; + lv_scale_mode_t mode; + uint32_t major_len; + uint32_t minor_len; int32_t range_min; int32_t range_max; uint32_t total_tick_count : 15; uint32_t major_tick_every : 15; - lv_scale_mode_t mode; uint32_t label_enabled : 1; - uint32_t post_draw : 1; - int32_t last_tick_width; - int32_t first_tick_width; + uint32_t post_draw : 1; /* Round scale */ uint32_t angle_range; int32_t rotation; + /* Private properties */ + int32_t custom_label_cnt; + int32_t last_tick_width; + int32_t first_tick_width; } lv_scale_t; LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_scale_class; @@ -125,14 +126,14 @@ void lv_scale_set_mode(lv_obj_t * obj, lv_scale_mode_t mode); * @param obj pointer the scale object * @param total_tick_count New total tick count */ -void lv_scale_set_total_tick_count(lv_obj_t * obj, int32_t total_tick_count); +void lv_scale_set_total_tick_count(lv_obj_t * obj, uint32_t total_tick_count); /** * Sets how often the major tick will be drawn * @param obj pointer the scale object * @param major_tick_every the new count for major tick drawing */ -void lv_scale_set_major_tick_every(lv_obj_t * obj, int32_t major_tick_every); +void lv_scale_set_major_tick_every(lv_obj_t * obj, uint32_t major_tick_every); /** * Sets label visibility @@ -146,14 +147,14 @@ void lv_scale_set_label_show(lv_obj_t * obj, bool show_label); * @param obj pointer the scale object * @param major_len major tick length */ -void lv_scale_set_major_tick_length(lv_obj_t * obj, int32_t major_len); +void lv_scale_set_major_tick_length(lv_obj_t * obj, uint32_t major_len); /** * Sets major tick length * @param obj pointer the scale object * @param minor_len minor tick length */ -void lv_scale_set_minor_tick_length(lv_obj_t * obj, int32_t minor_len); +void lv_scale_set_minor_tick_length(lv_obj_t * obj, uint32_t minor_len); /** * Set the minimal and maximal values on a scale @@ -239,6 +240,55 @@ void lv_scale_section_set_style(lv_scale_section_t * section, uint32_t part, lv_ * Getter functions *====================*/ +/** + * Get scale mode. See @ref lv_scale_mode_t + * @param obj pointer the scale object + * @return Scale mode + */ +lv_scale_mode_t lv_scale_get_mode(lv_obj_t * obj); + +/** + * Get scale total tick count (including minor and major ticks) + * @param obj pointer the scale object + * @return Scale total tick count + */ +int32_t lv_scale_get_total_tick_count(lv_obj_t * obj); + +/** + * Gets how often the major tick will be drawn + * @param obj pointer the scale object + * @return Scale major tick every count + */ +int32_t lv_scale_get_major_tick_every(lv_obj_t * obj); + +/** + * Gets label visibility + * @param obj pointer the scale object + * @return true if tick label is enabled, false otherwise + */ +bool lv_scale_get_label_show(lv_obj_t * obj); + +/** + * Get angle range of a round scale + * @param obj pointer to a scale object + * @return Scale angle_range + */ +uint32_t lv_scale_get_angle_range(lv_obj_t * obj); + +/** + * Get the min range for the given scale section + * @param obj pointer to a scale section object + * @return section minor range + */ +int32_t lv_scale_get_range_min_value(lv_obj_t * obj); + +/** + * Get the max range for the given scale section + * @param obj pointer to a scale section object + * @return section max range + */ +int32_t lv_scale_get_range_max_value(lv_obj_t * obj); + /********************** * MACROS **********************/ diff --git a/tests/ref_imgs/scale_1.png b/tests/ref_imgs/scale_1.png new file mode 100644 index 000000000..b35769b4a Binary files /dev/null and b/tests/ref_imgs/scale_1.png differ diff --git a/tests/ref_imgs/scale_2.png b/tests/ref_imgs/scale_2.png new file mode 100644 index 000000000..a82f560a3 Binary files /dev/null and b/tests/ref_imgs/scale_2.png differ diff --git a/tests/ref_imgs/scale_3.png b/tests/ref_imgs/scale_3.png new file mode 100644 index 000000000..9bf8d1d9b Binary files /dev/null and b/tests/ref_imgs/scale_3.png differ diff --git a/tests/ref_imgs/scale_4.png b/tests/ref_imgs/scale_4.png new file mode 100644 index 000000000..e079f132f Binary files /dev/null and b/tests/ref_imgs/scale_4.png differ diff --git a/tests/src/test_cases/widgets/test_scale.c b/tests/src/test_cases/widgets/test_scale.c new file mode 100644 index 000000000..41155e55a --- /dev/null +++ b/tests/src/test_cases/widgets/test_scale.c @@ -0,0 +1,367 @@ +#if LV_BUILD_TEST +#include "../lvgl.h" + +#include "unity/unity.h" + +/* Function run before every test */ +void setUp(void) +{ +} + +/* Function run after every test */ +void tearDown(void) +{ + lv_obj_clean(lv_screen_active()); +} + +/* A simple horizontal scale */ +void test_scale_render_example_1(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_scale_set_major_tick_length(scale, 10); + lv_scale_set_minor_tick_length(scale, 5); + lv_scale_set_range(scale, 10, 40); + + TEST_ASSERT_EQUAL_SCREENSHOT("scale_1.png"); +} + +/* An vertical scale with section and custom styling */ +void test_scale_render_example_2(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + lv_obj_set_size(scale, 60, 200); + lv_scale_set_label_show(scale, true); + lv_scale_set_mode(scale, LV_SCALE_MODE_VERTICAL_RIGHT); + lv_obj_center(scale); + + lv_scale_set_total_tick_count(scale, 21); + lv_scale_set_major_tick_every(scale, 5); + + lv_scale_set_major_tick_length(scale, 10); + lv_scale_set_minor_tick_length(scale, 5); + lv_scale_set_range(scale, 0, 100); + + static const char * custom_labels[] = {"0 °C", "25 °C", "50 °C", "75 °C", "100 °C", NULL}; + lv_scale_set_text_src(scale, custom_labels); + + static lv_style_t indicator_style; + lv_style_init(&indicator_style); + + /* Label style properties */ + lv_style_set_text_font(&indicator_style, &lv_font_montserrat_14); + lv_style_set_text_color(&indicator_style, lv_palette_darken(LV_PALETTE_BLUE, 3)); + + /* Major tick properties */ + lv_style_set_line_color(&indicator_style, lv_palette_darken(LV_PALETTE_BLUE, 3)); + lv_style_set_width(&indicator_style, 10U); /*Tick length*/ + lv_style_set_line_width(&indicator_style, 2U); /*Tick width*/ + lv_obj_add_style(scale, &indicator_style, LV_PART_INDICATOR); + + static lv_style_t minor_ticks_style; + lv_style_init(&minor_ticks_style); + lv_style_set_line_color(&minor_ticks_style, lv_palette_lighten(LV_PALETTE_BLUE, 2)); + lv_style_set_width(&minor_ticks_style, 5U); /*Tick length*/ + lv_style_set_line_width(&minor_ticks_style, 2U); /*Tick width*/ + lv_obj_add_style(scale, &minor_ticks_style, LV_PART_ITEMS); + + static lv_style_t main_line_style; + lv_style_init(&main_line_style); + /* Main line properties */ + lv_style_set_line_color(&main_line_style, lv_palette_darken(LV_PALETTE_BLUE, 3)); + lv_style_set_line_width(&main_line_style, 2U); // Tick width + lv_obj_add_style(scale, &main_line_style, LV_PART_MAIN); + + /* Add a section */ + static lv_style_t section_minor_tick_style; + static lv_style_t section_label_style; + static lv_style_t section_main_line_style; + + lv_style_init(§ion_label_style); + lv_style_init(§ion_minor_tick_style); + lv_style_init(§ion_main_line_style); + + /* Label style properties */ + lv_style_set_text_font(§ion_label_style, &lv_font_montserrat_14); + lv_style_set_text_color(§ion_label_style, lv_palette_darken(LV_PALETTE_RED, 3)); + + lv_style_set_line_color(§ion_label_style, lv_palette_darken(LV_PALETTE_RED, 3)); + lv_style_set_line_width(§ion_label_style, 5U); /*Tick width*/ + + lv_style_set_line_color(§ion_minor_tick_style, lv_palette_lighten(LV_PALETTE_RED, 2)); + lv_style_set_line_width(§ion_minor_tick_style, 4U); /*Tick width*/ + + /* Main line properties */ + lv_style_set_line_color(§ion_main_line_style, lv_palette_darken(LV_PALETTE_RED, 3)); + lv_style_set_line_width(§ion_main_line_style, 4U); /*Tick width*/ + + /* Configure section styles */ + lv_scale_section_t * section = lv_scale_add_section(scale); + lv_scale_section_set_range(section, 75, 100); + lv_scale_section_set_style(section, LV_PART_INDICATOR, §ion_label_style); + 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); + + lv_obj_set_style_bg_color(scale, lv_palette_main(LV_PALETTE_BLUE_GREY), 0); + lv_obj_set_style_bg_opa(scale, LV_OPA_50, 0); + lv_obj_set_style_pad_left(scale, 8, 0); + lv_obj_set_style_radius(scale, 8, 0); + lv_obj_set_style_pad_ver(scale, 20, 0); + + TEST_ASSERT_EQUAL_SCREENSHOT("scale_2.png"); +} + +/* A simple round scale */ +void test_scale_render_example_3(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + lv_obj_set_size(scale, 150, 150); + lv_scale_set_mode(scale, LV_SCALE_MODE_ROUND_INNER); + lv_obj_set_style_bg_opa(scale, LV_OPA_COVER, 0); + lv_obj_set_style_bg_color(scale, lv_palette_lighten(LV_PALETTE_RED, 5), 0); + lv_obj_set_style_radius(scale, LV_RADIUS_CIRCLE, 0); + lv_obj_center(scale); + + lv_scale_set_label_show(scale, true); + + lv_scale_set_total_tick_count(scale, 11); + lv_scale_set_major_tick_every(scale, 5); + + lv_scale_set_major_tick_length(scale, 10); + lv_scale_set_minor_tick_length(scale, 5); + lv_scale_set_range(scale, 10, 40); + + TEST_ASSERT_EQUAL_SCREENSHOT("scale_3.png"); +} + +/* A round scale with section and custom styling */ +void test_scale_render_example_4(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + lv_obj_set_size(scale, 150, 150); + lv_scale_set_label_show(scale, true); + lv_scale_set_mode(scale, LV_SCALE_MODE_ROUND_OUTER); + lv_obj_center(scale); + + lv_scale_set_total_tick_count(scale, 21); + lv_scale_set_major_tick_every(scale, 5); + + lv_scale_set_major_tick_length(scale, 10); + lv_scale_set_minor_tick_length(scale, 5); + lv_scale_set_range(scale, 0, 100); + + static const char * custom_labels[] = {"0 °C", "25 °C", "50 °C", "75 °C", "100 °C", NULL}; + lv_scale_set_text_src(scale, custom_labels); + + static lv_style_t indicator_style; + lv_style_init(&indicator_style); + + /* Label style properties */ + lv_style_set_text_font(&indicator_style, &lv_font_montserrat_14); + lv_style_set_text_color(&indicator_style, lv_palette_darken(LV_PALETTE_BLUE, 3)); + + /* Major tick properties */ + lv_style_set_line_color(&indicator_style, lv_palette_darken(LV_PALETTE_BLUE, 3)); + lv_style_set_width(&indicator_style, 10U); /*Tick length*/ + lv_style_set_line_width(&indicator_style, 2U); /*Tick width*/ + lv_obj_add_style(scale, &indicator_style, LV_PART_INDICATOR); + + static lv_style_t minor_ticks_style; + lv_style_init(&minor_ticks_style); + lv_style_set_line_color(&minor_ticks_style, lv_palette_lighten(LV_PALETTE_BLUE, 2)); + lv_style_set_width(&minor_ticks_style, 5U); /*Tick length*/ + lv_style_set_line_width(&minor_ticks_style, 2U); /*Tick width*/ + lv_obj_add_style(scale, &minor_ticks_style, LV_PART_ITEMS); + + static lv_style_t main_line_style; + lv_style_init(&main_line_style); + /* Main line properties */ + lv_style_set_arc_color(&main_line_style, lv_palette_darken(LV_PALETTE_BLUE, 3)); + lv_style_set_arc_width(&main_line_style, 2U); /*Tick width*/ + lv_obj_add_style(scale, &main_line_style, LV_PART_MAIN); + + /* Add a section */ + static lv_style_t section_minor_tick_style; + static lv_style_t section_label_style; + static lv_style_t section_main_line_style; + + lv_style_init(§ion_label_style); + lv_style_init(§ion_minor_tick_style); + lv_style_init(§ion_main_line_style); + + /* Label style properties */ + lv_style_set_text_font(§ion_label_style, &lv_font_montserrat_14); + lv_style_set_text_color(§ion_label_style, lv_palette_darken(LV_PALETTE_RED, 3)); + + lv_style_set_line_color(§ion_label_style, lv_palette_darken(LV_PALETTE_RED, 3)); + lv_style_set_line_width(§ion_label_style, 5U); /*Tick width*/ + + lv_style_set_line_color(§ion_minor_tick_style, lv_palette_lighten(LV_PALETTE_RED, 2)); + lv_style_set_line_width(§ion_minor_tick_style, 4U); /*Tick width*/ + + /* Main line properties */ + lv_style_set_arc_color(§ion_main_line_style, lv_palette_darken(LV_PALETTE_RED, 3)); + lv_style_set_arc_width(§ion_main_line_style, 4U); /*Tick width*/ + + /* Configure section styles */ + lv_scale_section_t * section = lv_scale_add_section(scale); + lv_scale_section_set_range(section, 75, 100); + lv_scale_section_set_style(section, LV_PART_INDICATOR, §ion_label_style); + 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"); +} + +void test_scale_set_style(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + + static lv_style_t section_minor_tick_style; + static lv_style_t section_label_style; + static lv_style_t section_main_line_style; + + lv_style_init(§ion_label_style); + lv_style_init(§ion_minor_tick_style); + lv_style_init(§ion_main_line_style); + + /* Configure section styles */ + lv_scale_section_t * section = lv_scale_add_section(scale); + lv_scale_section_set_range(section, 75, 100); + + lv_scale_section_set_style(section, LV_PART_MAIN, §ion_main_line_style); + TEST_ASSERT_NOT_NULL(section->main_style); + TEST_ASSERT_NULL(section->indicator_style); + TEST_ASSERT_NULL(section->items_style); + + TEST_ASSERT_EQUAL(section->main_style, §ion_main_line_style); + + lv_scale_section_set_style(section, LV_PART_INDICATOR, §ion_label_style); + TEST_ASSERT_NOT_NULL(section->main_style); + TEST_ASSERT_NOT_NULL(section->indicator_style); + TEST_ASSERT_NULL(section->items_style); + + TEST_ASSERT_EQUAL(section->main_style, §ion_main_line_style); + TEST_ASSERT_EQUAL(section->indicator_style, §ion_label_style); + + lv_scale_section_set_style(section, LV_PART_ITEMS, §ion_minor_tick_style); + TEST_ASSERT_NOT_NULL(section->main_style); + TEST_ASSERT_NOT_NULL(section->indicator_style); + TEST_ASSERT_NOT_NULL(section->items_style); + + TEST_ASSERT_EQUAL(section->main_style, §ion_main_line_style); + TEST_ASSERT_EQUAL(section->indicator_style, §ion_label_style); + TEST_ASSERT_EQUAL(section->items_style, §ion_minor_tick_style); + + /* Invalid part */ + lv_scale_section_set_style(section, LV_PART_CURSOR, §ion_minor_tick_style); + TEST_ASSERT_NOT_NULL(section->main_style); + TEST_ASSERT_NOT_NULL(section->indicator_style); + TEST_ASSERT_NOT_NULL(section->items_style); + + TEST_ASSERT_EQUAL(section->main_style, §ion_main_line_style); + TEST_ASSERT_EQUAL(section->indicator_style, §ion_label_style); + TEST_ASSERT_EQUAL(section->items_style, §ion_minor_tick_style); + + /* NULL section */ + lv_scale_section_t * null_section = NULL; + + lv_scale_section_set_range(null_section, 75, 100); + lv_scale_section_set_style(null_section, LV_PART_MAIN, §ion_main_line_style); +} + +/* The scale internally counts the number of custom labels until it finds the NULL sentinel */ +void test_scale_custom_labels_count(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + lv_scale_set_label_show(scale, true); + + static const char * custom_labels[] = {"0 °C", "25 °C", "50 °C", "75 °C", "100 °C", NULL}; + lv_scale_set_text_src(scale, custom_labels); + + lv_scale_t * scale_widget = (lv_scale_t *)scale; + + TEST_ASSERT_EQUAL(5U, scale_widget->custom_label_cnt); + + static const char * animal_labels[] = {"cat", "dog", NULL}; + lv_scale_set_text_src(scale, animal_labels); + + TEST_ASSERT_EQUAL(2U, scale_widget->custom_label_cnt); +} + +void test_scale_mode(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + + lv_scale_mode_t mode = LV_SCALE_MODE_ROUND_INNER; + lv_scale_set_mode(scale, mode); + + TEST_ASSERT_EQUAL(mode, lv_scale_get_mode(scale)); +} + +void test_scale_total_tick_count(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + + uint32_t total_tick_count = 42; + lv_scale_set_total_tick_count(scale, total_tick_count); + + TEST_ASSERT_EQUAL(total_tick_count, lv_scale_get_total_tick_count(scale)); +} + +void test_scale_major_tick_every(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + + uint32_t major_tick_every = 6; + lv_scale_set_major_tick_every(scale, major_tick_every); + + TEST_ASSERT_EQUAL(major_tick_every, lv_scale_get_major_tick_every(scale)); +} + +void test_scale_label_show(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + + bool label_show = true; + lv_scale_set_label_show(scale, label_show); + + TEST_ASSERT_EQUAL(label_show, lv_scale_get_label_show(scale)); + + label_show = false; + lv_scale_set_label_show(scale, label_show); + + TEST_ASSERT_EQUAL(label_show, lv_scale_get_label_show(scale)); +} + +void test_scale_angle_range(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + + uint32_t angle_range = 42; + lv_scale_set_angle_range(scale, angle_range); + + TEST_ASSERT_EQUAL(angle_range, lv_scale_get_angle_range(scale)); +} + +void test_scale_range(void) +{ + lv_obj_t * scale = lv_scale_create(lv_screen_active()); + + int32_t min_range = 24; + int32_t max_range = 42; + lv_scale_set_range(scale, min_range, max_range); + + TEST_ASSERT_EQUAL(min_range, lv_scale_get_range_min_value(scale)); + TEST_ASSERT_EQUAL(max_range, lv_scale_get_range_max_value(scale)); +} + +#endif