diff --git a/scripts/clang-formatter.sh b/scripts/clang-formatter.sh index d831917c3b..adf2a993db 100755 --- a/scripts/clang-formatter.sh +++ b/scripts/clang-formatter.sh @@ -2,12 +2,12 @@ clang-format-7 -style=file ../src/lv_core/*.c -i clang-format-7 -style=file ../src/lv_draw/*.c -i clang-format-7 -style=file ../src/lv_hal/*.c -i clang-format-7 -style=file ../src/lv_misc/*.c -i -clang-format-7 -style=file ../src/lv_objx/*.c -i +clang-format-7 -style=file ../src/lv_widgets/*.c -i clang-format-7 -style=file ../src/lv_themes/*.c -i clang-format-7 -style=file ../src/lv_core/*.h -i clang-format-7 -style=file ../src/lv_draw/*.h -i clang-format-7 -style=file ../src/lv_hal/*.h -i clang-format-7 -style=file ../src/lv_misc/*.h -i -clang-format-7 -style=file ../src/lv_objx/*.h -i +clang-format-7 -style=file ../src/lv_widgets/*.h -i clang-format-7 -style=file ../src/lv_themes/*.h -i diff --git a/src/lv_core/lv_obj_style_dec.h b/src/lv_core/lv_obj_style_dec.h index fdae2d08b7..6f92179763 100644 --- a/src/lv_core/lv_obj_style_dec.h +++ b/src/lv_core/lv_obj_style_dec.h @@ -174,9 +174,9 @@ _LV_OBJ_STYLE_SET_GET_DECLARE(TRANSITION_PROP_4, transition_prop_4, lv_style_int _LV_OBJ_STYLE_SET_GET_DECLARE(TRANSITION_PROP_5, transition_prop_5, lv_style_int_t, _int, scalar) _LV_OBJ_STYLE_SET_GET_DECLARE(TRANSITION_PROP_6, transition_prop_6, lv_style_int_t, _int, scalar) #if LV_USE_ANIMATION -_LV_OBJ_STYLE_SET_GET_DECLARE(TRANSITION_PATH, transition_path, const lv_anim_path_cb_t , _ptr, scalar) +_LV_OBJ_STYLE_SET_GET_DECLARE(TRANSITION_PATH, transition_path, lv_anim_path_cb_t , _ptr, scalar) #else -_LV_OBJ_STYLE_SET_GET_DECLARE(TRANSITION_PATH, transition_path, const void * , _ptr, scalar) /*For compatibility*/ +_LV_OBJ_STYLE_SET_GET_DECLARE(TRANSITION_PATH, transition_path, void * , _ptr, scalar) /*For compatibility*/ #endif _LV_OBJ_STYLE_SET_GET_DECLARE(SCALE_WIDTH, scale_width, lv_style_int_t, _int, scalar) _LV_OBJ_STYLE_SET_GET_DECLARE(SCALE_BORDER_WIDTH, scale_border_width, lv_style_int_t, _int, scalar) diff --git a/src/lv_misc/lv_log.c b/src/lv_misc/lv_log.c index acbdfb7327..2bf18acfd8 100644 --- a/src/lv_misc/lv_log.c +++ b/src/lv_misc/lv_log.c @@ -9,6 +9,9 @@ #include "lv_log.h" #if LV_USE_LOG +#include +#include "lv_printf.h" + #if LV_LOG_PRINTF #include #endif @@ -54,19 +57,25 @@ void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb) * @param level the level of log. (From `lv_log_level_t` enum) * @param file name of the file when the log added * @param line line number in the source code where the log added - * @param dsc description of the log + * @param format printf-like format string + * @param ... parameters for `format` */ -void lv_log_add(lv_log_level_t level, const char * file, int line, const char * dsc) +void lv_log_add(lv_log_level_t level, const char * file, int line, const char * format, ...) { if(level >= _LV_LOG_LEVEL_NUM) return; /*Invalid level*/ if(level >= LV_LOG_LEVEL) { + va_list args; + va_start(args, format); + char buf[256]; + lv_vsnprintf(buf, sizeof(buf), format, args); + va_end(args); #if LV_LOG_PRINTF - static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"}; - printf("%s: %s \t(%s #%d)\n", lvl_prefix[level], dsc, file, line); + static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error", "User"}; + printf("%s: %s \t(%s #%d)\n", lvl_prefix[level], buf, file, line); #else - if(custom_print_cb) custom_print_cb(level, file, line, dsc); + if(custom_print_cb) custom_print_cb(level, file, line, buf); #endif } } diff --git a/src/lv_misc/lv_log.h b/src/lv_misc/lv_log.h index d43db790b2..b84aa2d7b3 100644 --- a/src/lv_misc/lv_log.h +++ b/src/lv_misc/lv_log.h @@ -26,13 +26,15 @@ extern "C" { #define LV_LOG_LEVEL_INFO 1 /**< Log important events*/ #define LV_LOG_LEVEL_WARN 2 /**< Log if something unwanted happened but didn't caused problem*/ #define LV_LOG_LEVEL_ERROR 3 /**< Only critical issue, when the system may fail*/ -#define LV_LOG_LEVEL_NONE 4 /**< Do not log anything*/ -#define _LV_LOG_LEVEL_NUM 5 /**< Number of log levels */ +#define LV_LOG_LEVEL_USER 4 /**< Custom logs from the user*/ +#define LV_LOG_LEVEL_NONE 5 /**< Do not log anything*/ +#define _LV_LOG_LEVEL_NUM 6 /**< Number of log levels */ LV_EXPORT_CONST_INT(LV_LOG_LEVEL_TRACE); LV_EXPORT_CONST_INT(LV_LOG_LEVEL_INFO); LV_EXPORT_CONST_INT(LV_LOG_LEVEL_WARN); LV_EXPORT_CONST_INT(LV_LOG_LEVEL_ERROR); +LV_EXPORT_CONST_INT(LV_LOG_LEVEL_USER); LV_EXPORT_CONST_INT(LV_LOG_LEVEL_NONE); typedef int8_t lv_log_level_t; @@ -64,45 +66,55 @@ void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb); * @param level the level of log. (From `lv_log_level_t` enum) * @param file name of the file when the log added * @param line line number in the source code where the log added - * @param dsc description of the log + * @param format printf-like format string + * @param ... parameters for `format` */ -void lv_log_add(lv_log_level_t level, const char * file, int line, const char * dsc); +void lv_log_add(lv_log_level_t level, const char * file, int line, const char * format, ...); /********************** * MACROS **********************/ #if LV_LOG_LEVEL <= LV_LOG_LEVEL_TRACE -#define LV_LOG_TRACE(dsc) lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, dsc); +#define LV_LOG_TRACE(...) lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, __VA_ARGS__); #else -#define LV_LOG_TRACE(dsc) \ +#define LV_LOG_TRACE(...) \ { \ ; \ } #endif #if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO -#define LV_LOG_INFO(dsc) lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, dsc); +#define LV_LOG_INFO(...) lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__); #else -#define LV_LOG_INFO(dsc) \ +#define LV_LOG_INFO(...) \ { \ ; \ } #endif #if LV_LOG_LEVEL <= LV_LOG_LEVEL_WARN -#define LV_LOG_WARN(dsc) lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, dsc); +#define LV_LOG_WARN(...) lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, __VA_ARGS__); #else -#define LV_LOG_WARN(dsc) \ +#define LV_LOG_WARN(...) \ { \ ; \ } #endif #if LV_LOG_LEVEL <= LV_LOG_LEVEL_ERROR -#define LV_LOG_ERROR(dsc) lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, dsc); +#define LV_LOG_ERROR(...) lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__); #else -#define LV_LOG_ERROR(dsc) \ +#define LV_LOG_ERROR(...) \ + { \ + ; \ + } +#endif + +#if LV_LOG_LEVEL <= LV_LOG_LEVEL_USER +#define LV_LOG_USER(...) lv_log_add(LV_LOG_LEVEL_USER, __FILE__, __LINE__, __VA_ARGS__); +#else +#define LV_LOG_USER(...) \ { \ ; \ } @@ -111,23 +123,27 @@ void lv_log_add(lv_log_level_t level, const char * file, int line, const char * #else /*LV_USE_LOG*/ /*Do nothing if `LV_USE_LOG 0`*/ -#define lv_log_add(level, file, line, dsc) \ +#define lv_log_add(level, file, line, ...) \ { \ ; \ } -#define LV_LOG_TRACE(dsc) \ +#define LV_LOG_TRACE(...) \ { \ ; \ } -#define LV_LOG_INFO(dsc) \ +#define LV_LOG_INFO(...) \ { \ ; \ } -#define LV_LOG_WARN(dsc) \ +#define LV_LOG_WARN(...) \ { \ ; \ } -#define LV_LOG_ERROR(dsc) \ +#define LV_LOG_ERROR(...) \ + { \ + ; \ + } +#define LV_LOG_USER(...) \ { \ ; \ } diff --git a/src/lv_widgets/lv_bar.c b/src/lv_widgets/lv_bar.c index d9533099f0..cbb2b8eeb8 100644 --- a/src/lv_widgets/lv_bar.c +++ b/src/lv_widgets/lv_bar.c @@ -607,7 +607,6 @@ static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param) info->result = lv_bar_get_style(bar, info->part); if(info->result != NULL) return LV_RES_OK; else return ancestor_signal(bar, sign, param); - return LV_RES_OK; } /* Include the ancient signal function */ diff --git a/src/lv_widgets/lv_dropdown.c b/src/lv_widgets/lv_dropdown.c index 4e286ba64e..97c60dc6bd 100644 --- a/src/lv_widgets/lv_dropdown.c +++ b/src/lv_widgets/lv_dropdown.c @@ -534,6 +534,9 @@ void lv_dropdown_close(lv_obj_t * ddlist, lv_anim_enable_t anim) ext->pr_opt_id = LV_DROPDOWN_PR_NONE; if(ext->anim_time == 0 || anim == LV_ANIM_OFF) { +#if LV_USE_ANIMATION + lv_anim_del(ddlist, list_anim); +#endif lv_obj_del(ext->page); ext->page = NULL; } else { @@ -547,7 +550,10 @@ void lv_dropdown_close(lv_obj_t * ddlist, lv_anim_enable_t anim) lv_anim_set_time(&a, ext->anim_time); lv_anim_set_ready_cb(&a, close_anim_ready); lv_anim_start(&a); - + } else { + lv_anim_del(ddlist, list_anim); + lv_obj_del(ext->page); + ext->page = NULL; } #endif } diff --git a/src/lv_widgets/lv_msgbox.c b/src/lv_widgets/lv_msgbox.c index dde4acd49c..94efa6c2c0 100644 --- a/src/lv_widgets/lv_msgbox.c +++ b/src/lv_widgets/lv_msgbox.c @@ -365,7 +365,7 @@ bool lv_msgbox_get_recolor(const lv_obj_t * mbox) * @return pointer to button matrix object * @remarks return value will be NULL unless `lv_msgbox_add_btns` has been already called */ -lv_obj_t * lv_msgbox_get_btnm(lv_obj_t * mbox) +lv_obj_t * lv_msgbox_get_btnmatrix(lv_obj_t * mbox) { LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); diff --git a/src/lv_widgets/lv_msgbox.h b/src/lv_widgets/lv_msgbox.h index 48c0e15ba2..d1b9940eea 100644 --- a/src/lv_widgets/lv_msgbox.h +++ b/src/lv_widgets/lv_msgbox.h @@ -182,7 +182,7 @@ bool lv_msgbox_get_recolor(const lv_obj_t * mbox); * @return pointer to button matrix object * @remarks return value will be NULL unless `lv_msgbox_add_btns` has been already called */ -lv_obj_t * lv_msgbox_get_btnm(lv_obj_t * mbox); +lv_obj_t * lv_msgbox_get_btnmatrix(lv_obj_t * mbox); /********************** * MACROS diff --git a/src/lv_widgets/lv_roller.c b/src/lv_widgets/lv_roller.c index a58ca4af0e..a6557c370a 100644 --- a/src/lv_widgets/lv_roller.c +++ b/src/lv_widgets/lv_roller.c @@ -96,10 +96,9 @@ lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_signal_cb(roller, lv_roller_signal); lv_obj_set_design_cb(roller, lv_roller_design); - - /*Init the new roller roller*/ if(copy == NULL) { + lv_obj_t * label = lv_label_create(roller, NULL); lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); @@ -111,13 +110,11 @@ lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_signal_cb(scrl, lv_roller_scrl_signal); - lv_obj_clean_style_list(roller, LV_PAGE_PART_SCRL); /*Use a transparent scrollable*/ lv_theme_apply(roller, LV_THEME_ROLLER); refr_height(roller); lv_roller_set_visible_row_count(roller, 4); - } /*Copy an existing roller*/ else { @@ -148,6 +145,7 @@ void lv_roller_set_options(lv_obj_t * roller, const char * options, lv_roller_mo LV_ASSERT_OBJ(roller, LV_OBJX_NAME); LV_ASSERT_STR(options); + lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller); lv_obj_t * label = get_label(roller); @@ -169,7 +167,7 @@ void lv_roller_set_options(lv_obj_t * roller, const char * options, lv_roller_mo ext->mode = LV_ROLLER_MODE_INIFINITE; size_t opt_len = strlen(options) + 1; /*+1 to add '\n' after option lists*/ - char * opt_extra = lv_mem_alloc(opt_len * LV_ROLLER_INF_PAGES); + char * opt_extra = lv_mem_buf_get(opt_len * LV_ROLLER_INF_PAGES); uint8_t i; for(i = 0; i < LV_ROLLER_INF_PAGES; i++) { strcpy(&opt_extra[opt_len * i], options); @@ -177,7 +175,7 @@ void lv_roller_set_options(lv_obj_t * roller, const char * options, lv_roller_mo } opt_extra[opt_len * LV_ROLLER_INF_PAGES - 1] = '\0'; lv_label_set_text(label, opt_extra); - lv_mem_free(opt_extra); + lv_mem_buf_release(opt_extra); ext->sel_opt_id = ((LV_ROLLER_INF_PAGES / 2) + 1) * ext->option_cnt; @@ -245,6 +243,7 @@ void lv_roller_set_visible_row_count(lv_obj_t * roller, uint8_t row_cnt) lv_style_int_t line_space = lv_obj_get_style_text_line_space(roller, LV_ROLLER_PART_BG); lv_obj_set_height(roller, (lv_font_get_line_height(font) + line_space) * row_cnt); + refr_height(roller); refr_position(roller, LV_ANIM_OFF); } @@ -439,7 +438,7 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par lv_get_style_info_t * info = param; info->result = lv_roller_get_style(roller, info->part); if(info->result != NULL) return LV_RES_OK; - return LV_RES_OK; + else return ancestor_signal(roller, sign, param); } /*Don't let the drop down list to handle the control signals. It works differently*/ @@ -516,7 +515,9 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par } } } - + else if(sign == LV_SIGNAL_CLEANUP) { + lv_obj_clean_style_list(roller, LV_ROLLER_PART_SEL); + } return res; } @@ -835,7 +836,9 @@ static void inf_normalize(void * scrl) static lv_obj_t * get_label(const lv_obj_t * roller) { - return lv_obj_get_child(lv_page_get_scrl(roller), NULL); + lv_obj_t * scrl = lv_page_get_scrl(roller); + if(scrl == NULL) return NULL; /*The roller is being deleted, the scrollable already not exists*/ + return lv_obj_get_child(scrl, NULL); } #if LV_USE_ANIMATION diff --git a/src/lv_widgets/lv_textarea.c b/src/lv_widgets/lv_textarea.c index 260ca0e8f6..1438b5847e 100644 --- a/src/lv_widgets/lv_textarea.c +++ b/src/lv_widgets/lv_textarea.c @@ -22,7 +22,7 @@ /********************* * DEFINES *********************/ -#define LV_OBJX_NAME "lv_ta" +#define LV_OBJX_NAME "lv_textarea" /*Test configuration*/ #ifndef LV_TEXTAREA_DEF_CURSOR_BLINK_TIME @@ -59,7 +59,6 @@ static void pwd_char_hider_anim_ready(lv_anim_t * a); static void pwd_char_hider(lv_obj_t * ta); static bool char_is_accepted(lv_obj_t * ta, uint32_t c); static void refr_cursor_area(lv_obj_t * ta); -static void placeholder_update(lv_obj_t * ta); static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_indev_t * click_source); /********************** @@ -123,9 +122,10 @@ lv_obj_t * lv_textarea_create(lv_obj_t * par, const lv_obj_t * copy) ext->text_sel_en = 0; #endif ext->label = NULL; - ext->placeholder = NULL; + ext->placeholder_txt = NULL; lv_style_list_init(&ext->cursor.style); + lv_style_list_init(&ext->style_placeholder); #if LV_USE_ANIMATION == 0 ext->pwd_show_time = 0; @@ -167,13 +167,13 @@ lv_obj_t * lv_textarea_create(lv_obj_t * par, const lv_obj_t * copy) ext->cursor.hidden = copy_ext->cursor.hidden; lv_style_list_copy(&ext->cursor.style, ©_ext->cursor.style); + lv_style_list_copy(&ext->style_placeholder, ©_ext->style_placeholder); if(ext->pwd_mode != 0) pwd_char_hider( ta); - if(copy_ext->placeholder != NULL) - ext->placeholder = lv_label_create(ta, copy_ext->placeholder); - else - ext->placeholder = NULL; + if(copy_ext->placeholder_txt) { + lv_textarea_set_placeholder_text(ta, copy_ext->placeholder_txt); + } if(copy_ext->pwd_tmp) { uint16_t len = lv_mem_get_size(copy_ext->pwd_tmp); @@ -262,6 +262,12 @@ void lv_textarea_add_char(lv_obj_t * ta, uint32_t c) if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/ + /*If the textarea is empty, invalidate it to hide the placeholder*/ + if(ext->placeholder_txt) { + const char * txt = lv_label_get_text(ext->label); + if(txt[0] == '\0') lv_obj_invalidate(ta); + } + lv_label_ins_text(ext->label, ext->cursor.pos, (const char *)letter_buf); /*Insert the character*/ lv_textarea_clear_selection(ta); /*Clear selection*/ @@ -296,8 +302,6 @@ void lv_textarea_add_char(lv_obj_t * ta, uint32_t c) /*Revert the original edge flash state*/ lv_textarea_set_edge_flash(ta, edge_flash_en); - placeholder_update(ta); - lv_event_send(ta, LV_EVENT_VALUE_CHANGED, NULL); } @@ -341,6 +345,12 @@ void lv_textarea_add_text(lv_obj_t * ta, const char * txt) bool edge_flash_en = lv_textarea_get_edge_flash(ta); lv_textarea_set_edge_flash(ta, false); + /*If the textarea is empty, invalidate it to hide the placeholder*/ + if(ext->placeholder_txt) { + const char * txt = lv_label_get_text(ext->label); + if(txt[0] == '\0') lv_obj_invalidate(ta); + } + /*Insert the text*/ lv_label_ins_text(ext->label, ext->cursor.pos, txt); lv_textarea_clear_selection(ta); @@ -374,8 +384,6 @@ void lv_textarea_add_text(lv_obj_t * ta, const char * txt) /*Revert the original edge flash state*/ lv_textarea_set_edge_flash(ta, edge_flash_en); - placeholder_update(ta); - lv_event_send(ta, LV_EVENT_VALUE_CHANGED, NULL); } @@ -413,6 +421,13 @@ void lv_textarea_del_char(lv_obj_t * ta) lv_label_set_text(ext->label, label_txt); lv_textarea_clear_selection(ta); + + /*If the textarea became empty, invalidate it to hide the placeholder*/ + if(ext->placeholder_txt) { + const char * txt = lv_label_get_text(ext->label); + if(txt[0] == '\0') lv_obj_invalidate(ta); + } + /*Don't let 'width == 0' because cursor will not be visible*/ if(lv_obj_get_width(ext->label) == 0) { lv_style_int_t border_width = lv_obj_get_style_border_width(ta, LV_TEXTAREA_PART_CURSOR); @@ -431,8 +446,6 @@ void lv_textarea_del_char(lv_obj_t * ta) /*Move the cursor to the place of the deleted character*/ lv_textarea_set_cursor_pos(ta, ext->cursor.pos - 1); - placeholder_update(ta); - lv_event_send(ta, LV_EVENT_VALUE_CHANGED, NULL); } @@ -486,6 +499,13 @@ void lv_textarea_set_text(lv_obj_t * ta, const char * txt) lv_textarea_set_cursor_pos(ta, LV_TEXTAREA_CURSOR_LAST); } + + /*If the textarea is empty, invalidate it to hide the placeholder*/ + if(ext->placeholder_txt) { + const char * txt = lv_label_get_text(ext->label); + if(txt[0] == '\0') lv_obj_invalidate(ta); + } + /*Don't let 'width == 0' because the cursor will not be visible*/ if(lv_obj_get_width(ext->label) == 0) { lv_style_int_t border_width = lv_obj_get_style_border_width(ta, LV_TEXTAREA_PART_CURSOR); @@ -514,13 +534,11 @@ void lv_textarea_set_text(lv_obj_t * ta, const char * txt) #endif } - placeholder_update(ta); - lv_event_send(ta, LV_EVENT_VALUE_CHANGED, NULL); } /** - * Set the placeholder text of a text area + * Set the placeholder_txt text of a text area * @param ta pointer to a text area * @param txt pointer to the text */ @@ -531,25 +549,31 @@ void lv_textarea_set_placeholder_text(lv_obj_t * ta, const char * txt) lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); - /*Create the placeholder label only when it is needed*/ - if(ext->placeholder == NULL) { - ext->placeholder = lv_label_create(ta, NULL); + size_t txt_len = strlen(txt); - if(ext->one_line) { - lv_label_set_long_mode(ext->placeholder, LV_LABEL_LONG_EXPAND); - } else { - lv_label_set_long_mode(ext->placeholder, LV_LABEL_LONG_BREAK); + if(txt_len == 0) { + if(ext->placeholder_txt) { + lv_mem_free(ext->placeholder_txt); + ext->placeholder_txt = NULL; } + } else { - lv_theme_apply(ta, LV_THEME_TEXTAREA); + /*Allocate memory for the placeholder_txt text*/ + if(ext->placeholder_txt == NULL) { + ext->placeholder_txt = lv_mem_alloc(txt_len + 1); + } else { + ext->placeholder_txt = lv_mem_realloc(ext->placeholder_txt, txt_len + 1); + + } + LV_ASSERT_MEM(ext->placeholder_txt); + if(ext->placeholder_txt == NULL) { + LV_LOG_ERROR("lv_textarea_set_placeholder_text: couldn't allocate memory for placeholder"); + return; + } + strcpy(ext->placeholder_txt, txt); } - lv_label_set_text(ext->placeholder, txt); - - /*Refresh the placeholder's align*/ - lv_textarea_set_text_align(ta, lv_label_get_align(ext->label)); - - placeholder_update(ta); + lv_obj_invalidate(ta); } /** @@ -718,10 +742,9 @@ void lv_textarea_set_one_line(lv_obj_t * ta, bool en) lv_coord_t font_h = lv_font_get_line_height(font); ext->one_line = 1; - lv_page_set_scrl_fit2(ta, LV_FIT_TIGHT, LV_FIT_PARENT); + lv_page_set_scrl_fit2(ta, LV_FIT_MAX, LV_FIT_PARENT); lv_obj_set_height(ta, font_h + top + bottom); lv_label_set_long_mode(ext->label, LV_LABEL_LONG_EXPAND); - if(ext->placeholder) lv_label_set_long_mode(ext->placeholder, LV_LABEL_LONG_EXPAND); lv_obj_set_pos(lv_page_get_scrl(ta), left, top); } else { lv_style_int_t top = lv_obj_get_style_pad_top(ta, LV_TEXTAREA_PART_BG); @@ -729,13 +752,11 @@ void lv_textarea_set_one_line(lv_obj_t * ta, bool en) ext->one_line = 0; lv_page_set_scrl_fit2(ta, LV_FIT_PARENT, LV_FIT_TIGHT); lv_label_set_long_mode(ext->label, LV_LABEL_LONG_BREAK); - if(ext->placeholder) lv_label_set_long_mode(ext->placeholder, LV_LABEL_LONG_BREAK); lv_obj_set_height(ta, LV_TEXTAREA_DEF_HEIGHT); lv_obj_set_pos(lv_page_get_scrl(ta), left, top); } - placeholder_update(ta); /* `refr_cursor_area` is called at the end of lv_ta_set_text_align */ lv_textarea_set_text_align(ta, old_align); } @@ -755,23 +776,18 @@ void lv_textarea_set_text_align(lv_obj_t * ta, lv_label_align_t align) lv_obj_t * label = lv_textarea_get_label(ta); if(!ext->one_line) { lv_label_set_align(label, align); - if(ext->placeholder) lv_label_set_align(ext->placeholder, align); } else { /*Normal left align. Just let the text expand*/ if(align == LV_LABEL_ALIGN_LEFT) { lv_label_set_long_mode(label, LV_LABEL_LONG_EXPAND); - lv_page_set_scrl_fit2(ta, LV_FIT_TIGHT, LV_FIT_PARENT); + lv_page_set_scrl_fit2(ta, LV_FIT_MAX, LV_FIT_PARENT); lv_label_set_align(label, align); - if(ext->placeholder) lv_label_set_align(ext->placeholder, align); - } /*Else use fix label width equal to the Text area width*/ else { lv_label_set_long_mode(label, LV_LABEL_LONG_CROP); lv_page_set_scrl_fit2(ta, LV_FIT_PARENT, LV_FIT_PARENT); lv_label_set_align(label, align); - if(ext->placeholder) lv_label_set_align(ext->placeholder, align); - lv_obj_set_width(label, lv_page_get_fit_width(ta)); } } @@ -924,7 +940,7 @@ const char * lv_textarea_get_text(const lv_obj_t * ta) } /** - * Get the placeholder text of a text area + * Get the placeholder_txt text of a text area * @param ta pointer to a text area object * @return pointer to the text */ @@ -933,12 +949,8 @@ const char * lv_textarea_get_placeholder_text(lv_obj_t * ta) LV_ASSERT_OBJ(ta, LV_OBJX_NAME); lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); - - const char * txt = NULL; - - if(ext->placeholder) txt = lv_label_get_text(ext->placeholder); - - return txt; + if(ext->placeholder_txt) return ext->placeholder_txt; + else return ""; } /** @@ -1279,9 +1291,30 @@ static lv_design_res_t lv_textarea_scrollable_design(lv_obj_t * scrl, const lv_a } else if(mode == LV_DESIGN_DRAW_POST) { scrl_design(scrl, clip_area, mode); - /*Draw the cursor*/ lv_obj_t * ta = lv_obj_get_parent(scrl); lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); + const char * txt = lv_label_get_text(ext->label); + + /*Draw the place holder*/ + if(txt[0] == '\0' && ext->placeholder_txt && ext->placeholder_txt[0] != 0) { + lv_draw_label_dsc_t ph_dsc; + lv_draw_label_dsc_init(&ph_dsc); + lv_obj_init_draw_label_dsc(ta, LV_TEXTAREA_PART_PLACEHOLDER, &ph_dsc); + switch(lv_label_get_align(ext->label)) { + case LV_LABEL_ALIGN_CENTER: + ph_dsc.flag |= LV_TXT_FLAG_CENTER; + break; + case LV_LABEL_ALIGN_RIGHT: + ph_dsc.flag |= LV_TXT_FLAG_RIGHT; + break; + default: + break; + } + + lv_draw_label(&scrl->coords, clip_area, &ph_dsc, ext->placeholder_txt, NULL); + } + + /*Draw the cursor*/ if(ext->cursor.hidden|| ext->cursor.state == 0) { return LV_DESIGN_RES_OK; /*The cursor is not visible now*/ @@ -1291,8 +1324,6 @@ static lv_design_res_t lv_textarea_scrollable_design(lv_obj_t * scrl, const lv_a lv_draw_rect_dsc_init(&cur_dsc); lv_obj_init_draw_rect_dsc(ta, LV_TEXTAREA_PART_CURSOR, &cur_dsc); - const char * txt = lv_label_get_text(ext->label); - /*Draw he cursor according to the type*/ lv_area_t cur_area; lv_area_copy(&cur_area, &ext->cursor.area); @@ -1338,16 +1369,8 @@ static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param info->result = lv_textarea_get_style(ta, info->part); if(info->result != NULL) return LV_RES_OK; else return ancestor_signal(ta, sign, param); - }else if(sign == LV_SIGNAL_GET_STATE_DSC) { - lv_textarea_ext_t * ext = ta->ext_attr; - lv_get_state_info_t * info = param; - if(info->part == LV_TEXTAREA_PART_PLACEHOLDER) { - if(ext->placeholder) { - info->result = lv_obj_get_state(ext->placeholder, LV_LABEL_PART_MAIN); - } - return LV_RES_OK; - } - else return ancestor_signal(ta, sign, param); + } else if(sign == LV_SIGNAL_GET_STATE_DSC) { + return ancestor_signal(ta, sign, param); } /* Include the ancient signal function */ @@ -1358,9 +1381,16 @@ static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); if(sign == LV_SIGNAL_CLEANUP) { if(ext->pwd_tmp != NULL) lv_mem_free(ext->pwd_tmp); - /* (The created label will be deleted automatically) */ + if(ext->placeholder_txt != NULL) lv_mem_free(ext->placeholder_txt); + + ext->pwd_tmp = NULL; + ext->placeholder_txt = NULL; lv_obj_clean_style_list(ta, LV_TEXTAREA_PART_CURSOR); + lv_obj_clean_style_list(ta, LV_TEXTAREA_PART_PLACEHOLDER); + + /* (The created label will be deleted automatically) */ + } else if(sign == LV_SIGNAL_STYLE_CHG) { if(ext->label) { if(ext->one_line) { @@ -1377,10 +1407,6 @@ static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param lv_obj_set_width(ext->label, lv_page_get_fit_width(ta)); lv_obj_set_pos(ext->label, 0, 0); /*Be sure the Label is in the correct position*/ - if(ext->placeholder) { - lv_obj_set_width(ext->placeholder, lv_page_get_fit_width(ta)); - lv_obj_set_pos(ext->placeholder, 0, 0); /*Be sure the placeholder is in the correct position*/ - } } lv_label_set_text(ext->label, NULL); refr_cursor_area(ta); @@ -1393,16 +1419,6 @@ static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param lv_obj_set_pos(ext->label, 0, 0); lv_label_set_text(ext->label, NULL); /*Refresh the label*/ - refr_cursor_area(ta); - } - } - /*Set the placeholder width according to the text area width*/ - if(ext->placeholder) { - if(lv_obj_get_width(ta) != lv_area_get_width(param) || lv_obj_get_height(ta) != lv_area_get_height(param)) { - lv_obj_set_width(ext->placeholder, lv_page_get_fit_width(ta)); - lv_obj_set_pos(ext->placeholder, 0, 0); - lv_label_set_text(ext->placeholder, NULL); /*Refresh the label*/ - refr_cursor_area(ta); } } @@ -1535,7 +1551,7 @@ static lv_style_list_t * lv_textarea_get_style(lv_obj_t * ta, uint8_t part) break; #endif case LV_TEXTAREA_PART_PLACEHOLDER: - style_dsc_p = ext->placeholder ? lv_obj_get_style_list(ext->placeholder, LV_LABEL_PART_MAIN) : NULL; + style_dsc_p = &ext->style_placeholder; break; default: style_dsc_p = NULL; @@ -1742,27 +1758,6 @@ static void refr_cursor_area(lv_obj_t * ta) lv_obj_invalidate_area(ta, &area_tmp); } -static void placeholder_update(lv_obj_t * ta) -{ - lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); - const char * ta_text; - - if(ext->placeholder == NULL) return; - - ta_text = lv_textarea_get_text(ta); - - if(ta_text[0] == '\0') { - /*Be sure the main label and the placeholder has the same coordinates*/ - lv_obj_set_pos(ext->placeholder, 0, 0); - lv_obj_set_pos(ext->label, 0, 0); - - lv_obj_set_width(ext->placeholder, lv_page_get_fit_width(ta)); - lv_obj_set_hidden(ext->placeholder, false); - } else { - lv_obj_set_hidden(ext->placeholder, true); - } -} - static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_indev_t * click_source) { diff --git a/src/lv_widgets/lv_textarea.h b/src/lv_widgets/lv_textarea.h index adb951186d..24fa58f1a2 100644 --- a/src/lv_widgets/lv_textarea.h +++ b/src/lv_widgets/lv_textarea.h @@ -47,7 +47,8 @@ typedef struct lv_page_ext_t page; /*Ext. of ancestor*/ /*New data for this type */ lv_obj_t * label; /*Label of the text area*/ - lv_obj_t * placeholder; /*Place holder label. only visible if text is an empty string*/ + char * placeholder_txt; /*Place holder label. only visible if text is an empty string*/ + lv_style_list_t style_placeholder; char * pwd_tmp; /*Used to store the original text in password mode*/ const char * accapted_chars; /*Only these characters will be accepted. NULL: accept all*/ uint16_t max_length; /*The max. number of characters. 0: no limit*/ @@ -82,10 +83,10 @@ enum { LV_TEXTAREA_PART_SCRLBAR = LV_PAGE_PART_SCRLBAR, /**< Scrollbar style */ LV_TEXTAREA_PART_EDGE_FLASH = LV_PAGE_PART_EDGE_FLASH, /**< Edge flash style */ LV_TEXTAREA_PART_CURSOR = _LV_PAGE_PART_VIRTUAL_LAST, /**< Cursor style */ + LV_TEXTAREA_PART_PLACEHOLDER, /**< Placeholder style */ _LV_TEXTAREA_PART_VIRTUAL_LAST, - LV_TEXTAREA_PART_PLACEHOLDER = _LV_PAGE_PART_REAL_LAST, /**< Placeholder style */ - _LV_TEXTAREA_PART_REAL_LAST, + _LV_TEXTAREA_PART_REAL_LAST = _LV_PAGE_PART_REAL_LAST, }; typedef uint8_t lv_textarea_style_t;