From eef838f51f10f72874c2914be79e09634606107e Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 30 May 2022 12:05:22 +0200 Subject: [PATCH] feat(textarea): make it possible to customize the bullet character (#3388) * feat(textarea): Make it possible to customise the bullet character This adds functions to allow overriding the default bullet character with a custom one (or even no character at all). * Update docs/widgets/core/textarea.md Co-authored-by: Gabor Kiss-Vamosi Co-authored-by: Gabor Kiss-Vamosi --- docs/widgets/core/textarea.md | 3 +- src/widgets/lv_textarea.c | 60 +++++++++++++++++++++++++++++++---- src/widgets/lv_textarea.h | 15 +++++++++ 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/docs/widgets/core/textarea.md b/docs/widgets/core/textarea.md index 2bedb7fc1..3beadd5c6 100644 --- a/docs/widgets/core/textarea.md +++ b/docs/widgets/core/textarea.md @@ -63,8 +63,7 @@ In this mode the height is set automatically to show only one line, line break c ### Password mode The text area supports password mode which can be enabled with `lv_textarea_set_password_mode(textarea, true)`. -If the `•` ([Bullet, U+2022](http://www.fileformat.info/info/unicode/char/2022/index.htm)) character exists in the font, the entered characters are converted to it after some time or when a new character is entered. -If `•` not exists, `*` will be used. +By default, if the `•` ([Bullet, U+2022](http://www.fileformat.info/info/unicode/char/2022/index.htm)) character exists in the font, the entered characters are converted to it after some time or when a new character is entered. If `•` does not exist in the font, `*` will be used. You can override the default character with `lv_textarea_set_password_bullet(textarea, "x")`. In password mode `lv_textarea_get_text(textarea)` returns the actual text entered, not the bullet characters. diff --git a/src/widgets/lv_textarea.c b/src/widgets/lv_textarea.c index 8624b01d0..4d497e669 100644 --- a/src/widgets/lv_textarea.c +++ b/src/widgets/lv_textarea.c @@ -435,6 +435,36 @@ void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) refr_cursor_area(obj); } +void lv_textarea_set_password_bullet(lv_obj_t * obj, const char * bullet) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(bullet); + + lv_textarea_t * ta = (lv_textarea_t *)obj; + + if(!bullet && (ta->pwd_bullet)) { + lv_mem_free(ta->pwd_bullet); + ta->pwd_bullet = NULL; + } + else { + size_t txt_len = strlen(bullet); + + /*Allocate memory for the pwd_bullet text*/ + /*NOTE: Using special realloc behavior, malloc-like when data_p is NULL*/ + ta->pwd_bullet = lv_mem_realloc(ta->pwd_bullet, txt_len + 1); + LV_ASSERT_MALLOC(ta->pwd_bullet); + if(ta->pwd_bullet == NULL) { + LV_LOG_ERROR("lv_textarea_set_password_bullet: couldn't allocate memory for bullet"); + return; + } + + strcpy(ta->pwd_bullet, bullet); + ta->pwd_bullet[txt_len] = '\0'; + } + + lv_obj_invalidate(obj); +} + void lv_textarea_set_one_line(lv_obj_t * obj, bool en) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -590,6 +620,23 @@ bool lv_textarea_get_password_mode(const lv_obj_t * obj) return ta->pwd_mode == 1U; } +const char * lv_textarea_get_password_bullet(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_textarea_t * ta = (lv_textarea_t *)obj; + + if(ta->pwd_bullet) return ta->pwd_bullet; + + lv_font_glyph_dsc_t g; + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + + /*If the textarea's font has the bullet character use it else fallback to "*"*/ + if(lv_font_get_glyph_dsc(font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, 0)) + return LV_SYMBOL_BULLET; + return "*"; +} + bool lv_textarea_get_one_line(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -764,6 +811,7 @@ static void lv_textarea_constructor(const lv_obj_class_t * class_p, lv_obj_t * o ta->pwd_mode = 0; ta->pwd_tmp = NULL; + ta->pwd_bullet = NULL; ta->pwd_show_time = LV_TEXTAREA_DEF_PWD_SHOW_TIME; ta->accepted_chars = NULL; ta->max_length = 0; @@ -800,6 +848,10 @@ static void lv_textarea_destructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_mem_free(ta->pwd_tmp); ta->pwd_tmp = NULL; } + if(ta->pwd_bullet != NULL) { + lv_mem_free(ta->pwd_bullet); + ta->pwd_bullet = NULL; + } if(ta->placeholder_txt != NULL) { lv_mem_free(ta->placeholder_txt); ta->placeholder_txt = NULL; @@ -931,13 +983,7 @@ static void pwd_char_hider(lv_obj_t * obj) uint32_t enc_len = _lv_txt_get_encoded_length(txt); if(enc_len == 0) return; - /*If the textarea's font has "bullet" character use it else fallback to "*"*/ - lv_font_glyph_dsc_t g; - const char * bullet = "*"; - - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - if(lv_font_get_glyph_dsc(font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, 0)) bullet = LV_SYMBOL_BULLET; - + const char * bullet = lv_textarea_get_password_bullet(obj); const size_t bullet_len = strlen(bullet); char * txt_tmp = lv_mem_buf_get(enc_len * bullet_len + 1); diff --git a/src/widgets/lv_textarea.h b/src/widgets/lv_textarea.h index 219e2725e..4b3289b48 100644 --- a/src/widgets/lv_textarea.h +++ b/src/widgets/lv_textarea.h @@ -42,6 +42,7 @@ typedef struct { lv_obj_t * label; /*Label of the text area*/ char * placeholder_txt; /*Place holder label. only visible if text is an empty string*/ char * pwd_tmp; /*Used to store the original text in password mode*/ + char * pwd_bullet; /*Replacement characters displayed in password mode*/ const char * accepted_chars; /*Only these characters will be accepted. NULL: accept all*/ uint32_t max_length; /*The max. number of characters. 0: no limit*/ uint16_t pwd_show_time; /*Time to show characters in password mode before change them to '*'*/ @@ -154,6 +155,13 @@ void lv_textarea_set_cursor_click_pos(lv_obj_t * obj, bool en); */ void lv_textarea_set_password_mode(lv_obj_t * obj, bool en); +/** + * Set the replacement characters to show in password mode + * @param obj pointer to a text area object + * @param bullet pointer to the replacement text + */ +void lv_textarea_set_password_bullet(lv_obj_t * obj, const char * bullet); + /** * Configure the text area to one line or back to normal * @param obj pointer to a text area object @@ -254,6 +262,13 @@ bool lv_textarea_get_cursor_click_pos(lv_obj_t * obj); */ bool lv_textarea_get_password_mode(const lv_obj_t * obj); +/** + * Get the replacement characters to show in password mode + * @param obj pointer to a text area object + * @return pointer to the replacement text + */ +const char * lv_textarea_get_password_bullet(lv_obj_t * obj); + /** * Get the one line configuration attribute * @param obj pointer to a text area object