From c27760fb103dbcee94bbc2751e741fb55ffa8f35 Mon Sep 17 00:00:00 2001 From: Luna <23561952+Orange-Murker@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:27:38 +0100 Subject: [PATCH] feat(roller): set roller option with a string (#7143) Co-authored-by: Gabor Kiss-Vamosi --- docs/details/widgets/roller.rst | 4 ++++ src/stdlib/builtin/lv_string_builtin.c | 16 +++++++++++++ src/stdlib/clib/lv_string_clib.c | 5 ++++ src/stdlib/lv_string.h | 9 +++++++ src/stdlib/rtthread/lv_string_rtthread.c | 5 ++++ src/widgets/roller/lv_roller.c | 28 ++++++++++++++++++++++ src/widgets/roller/lv_roller.h | 10 ++++++++ tests/src/test_cases/widgets/test_roller.c | 19 +++++++++++++++ 8 files changed, 96 insertions(+) diff --git a/docs/details/widgets/roller.rst b/docs/details/widgets/roller.rst index 0653cb641..8ed18d511 100644 --- a/docs/details/widgets/roller.rst +++ b/docs/details/widgets/roller.rst @@ -43,6 +43,10 @@ You can select an option manually with :cpp:expr:`lv_roller_set_selected(roller, id, LV_ANIM_ON)`, where *id* is the index of an option. +If you don't know the index of an option can also select an option with +:cpp:expr:`lv_roller_set_selected_str(roller, str, LV_ANIM_ON)`, +where *str* is the string equal to one of the options. + Get selected option ------------------- diff --git a/src/stdlib/builtin/lv_string_builtin.c b/src/stdlib/builtin/lv_string_builtin.c index 4ecbe0291..f83399f2d 100644 --- a/src/stdlib/builtin/lv_string_builtin.c +++ b/src/stdlib/builtin/lv_string_builtin.c @@ -232,6 +232,22 @@ int lv_strcmp(const char * s1, const char * s2) return *(const unsigned char *)s1 - *(const unsigned char *)s2; } +int lv_strncmp(const char * s1, const char * s2, size_t len) +{ + if(len == 0) { + return 0; + } + + while(len > 0 && *s1 && (*s1 == *s2)) { + if(--len == 0) { + return 0; + } + s1++; + s2++; + } + return *(const unsigned char *)s1 - *(const unsigned char *)s2; +} + char * lv_strdup(const char * src) { size_t len = lv_strlen(src) + 1; diff --git a/src/stdlib/clib/lv_string_clib.c b/src/stdlib/clib/lv_string_clib.c index 96bae8b4e..7474cb5d3 100644 --- a/src/stdlib/clib/lv_string_clib.c +++ b/src/stdlib/clib/lv_string_clib.c @@ -86,6 +86,11 @@ int lv_strcmp(const char * s1, const char * s2) return strcmp(s1, s2); } +int lv_strncmp(const char * s1, const char * s2, size_t len) +{ + return strncmp(s1, s2, len); +} + char * lv_strdup(const char * src) { /*strdup uses malloc, so use the lv_malloc when LV_USE_STDLIB_MALLOC is not LV_STDLIB_CLIB */ diff --git a/src/stdlib/lv_string.h b/src/stdlib/lv_string.h index ce73502e1..d9101a512 100644 --- a/src/stdlib/lv_string.h +++ b/src/stdlib/lv_string.h @@ -119,6 +119,15 @@ char * lv_strcpy(char * dst, const char * src); */ int lv_strcmp(const char * s1, const char * s2); +/** + * @brief This function will compare two strings up to the given length. + * @param s1 pointer to the first string + * @param s2 pointer to the second string + * @param len the maximum amount of characters to compare + * @return the difference between the value of the first unmatching character. + */ +int lv_strncmp(const char * s1, const char * s2, size_t len); + /** * @brief Duplicate a string by allocating a new one and copying the content. * @param src Pointer to the source of data to be copied. diff --git a/src/stdlib/rtthread/lv_string_rtthread.c b/src/stdlib/rtthread/lv_string_rtthread.c index 26cf4f8f8..f67769558 100644 --- a/src/stdlib/rtthread/lv_string_rtthread.c +++ b/src/stdlib/rtthread/lv_string_rtthread.c @@ -86,6 +86,11 @@ int lv_strcmp(const char * s1, const char * s2) return rt_strcmp(s1, s2); } +int lv_strncmp(const char * s1, const char * s2, size_t len) +{ + return rt_strncmp(s1, s2, len); +} + char * lv_strdup(const char * src) { size_t len = lv_strlen(src) + 1; diff --git a/src/widgets/roller/lv_roller.c b/src/widgets/roller/lv_roller.c index 3fd5fe7a2..478a65b49 100644 --- a/src/widgets/roller/lv_roller.c +++ b/src/widgets/roller/lv_roller.c @@ -275,6 +275,34 @@ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_s buf[c] = '\0'; } +bool lv_roller_set_selected_str(lv_obj_t * obj, const char * sel_opt, lv_anim_enable_t anim) +{ + const char * options = lv_roller_get_options(obj); + size_t options_len = lv_strlen(options); + + bool option_found = false; + + uint32_t current_option = 0; + size_t line_start = 0; + + for(size_t i = 0; i < options_len; i++) { + if(options[i] == '\n') { + /* See if this is the correct option */ + if(lv_strncmp(&options[line_start], sel_opt, i - line_start) == 0) { + lv_roller_set_selected(obj, current_option, anim); + option_found = true; + break; + } + + current_option++; + line_start = i + 1; + } + } + + return option_found; +} + + /** * Get the options of a roller * @param roller pointer to roller object diff --git a/src/widgets/roller/lv_roller.h b/src/widgets/roller/lv_roller.h index e6a94b299..9a28dcf29 100644 --- a/src/widgets/roller/lv_roller.h +++ b/src/widgets/roller/lv_roller.h @@ -106,6 +106,16 @@ uint32_t lv_roller_get_selected(const lv_obj_t * obj); */ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_size); + +/** + * Sets the given string as the selection on the roller. Does not alter the current selection on failure. + * @param obj pointer to roller object + * @param sel_opt pointer to the string you want to set as an option + * @param anim LV_ANIM_ON: set with animation; LV_ANOM_OFF set immediately + * @return `true` if set successfully and `false` if the given string does not exist as an option in the roller + */ +bool lv_roller_set_selected_str(lv_obj_t * obj, const char * sel_opt, lv_anim_enable_t anim); + /** * Get the options of a roller * @param obj pointer to roller object diff --git a/tests/src/test_cases/widgets/test_roller.c b/tests/src/test_cases/widgets/test_roller.c index acfc47975..e04f0e57e 100644 --- a/tests/src/test_cases/widgets/test_roller.c +++ b/tests/src/test_cases/widgets/test_roller.c @@ -125,6 +125,25 @@ void test_roller_infinite_mode_get_selected_option(void) TEST_ASSERT_EQUAL_STRING("Two", actual_str); } +void test_roller_set_selected_option_str(void) +{ + bool selected; + TEST_ASSERT_EQUAL(0, lv_roller_get_selected(roller)); + + /* Test an item that exists in the roller */ + selected = lv_roller_set_selected_str(roller, "Two", LV_ANIM_OFF); + TEST_ASSERT_TRUE(selected); + + TEST_ASSERT_EQUAL(1, lv_roller_get_selected(roller)); + + /* Try to select an item that does not exist in the roller */ + selected = lv_roller_set_selected_str(roller, "No", LV_ANIM_OFF); + TEST_ASSERT_FALSE(selected); + + /* Make sure that the selection did not change */ + TEST_ASSERT_EQUAL(1, lv_roller_get_selected(roller)); +} + void test_roller_keypad_events(void) { int16_t expected_index = 1;