diff --git a/lv_objx/lv_label.c b/lv_objx/lv_label.c index 106ba564c..1ef781caf 100644 --- a/lv_objx/lv_label.c +++ b/lv_objx/lv_label.c @@ -555,7 +555,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) uint32_t i = line_start; uint32_t i_current = i; uint32_t letter; - while(i < new_line_start - 1) { + while(i <= new_line_start - 1) { letter = lv_txt_encoded_next(txt, &i); /*Be careful 'i' already points to the next character*/ /*Handle the recolor command*/ if((flag & LV_TXT_FLAG_RECOLOR) != 0) { diff --git a/lv_objx/lv_ta.c b/lv_objx/lv_ta.c index 98bd86468..8199cd3e3 100644 --- a/lv_objx/lv_ta.c +++ b/lv_objx/lv_ta.c @@ -53,6 +53,7 @@ static void pwd_char_hider(lv_obj_t * ta); static bool char_is_accepted(lv_obj_t * ta, uint32_t c); static void get_cursor_style(lv_obj_t * ta, lv_style_t * style_res); 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_indev_t * click_source); /********************** @@ -248,6 +249,8 @@ void lv_ta_add_char(lv_obj_t * ta, uint32_t c) /*Revert the original edge flash state*/ lv_ta_set_edge_flash(ta, edge_flash_en); + + placeholder_update(ta); } /** @@ -311,6 +314,8 @@ void lv_ta_add_text(lv_obj_t * ta, const char * txt) /*Revert the original edge flash state*/ lv_ta_set_edge_flash(ta, edge_flash_en); + + placeholder_update(ta); } /** @@ -350,6 +355,8 @@ void lv_ta_del_char(lv_obj_t * ta) /*Move the cursor to the place of the deleted character*/ lv_ta_set_cursor_pos(ta, ext->cursor.pos - 1); + + placeholder_update(ta); } /** @@ -423,6 +430,33 @@ void lv_ta_set_text(lv_obj_t * ta, const char * txt) pwd_char_hider(ta); #endif } + + placeholder_update(ta); +} + +/** +* Set the placeholder text of a text area +* @param ta pointer to a text area +* @param txt pointer to the text +*/ +void lv_ta_set_placeholder_text(lv_obj_t * ta, const char * txt) +{ + lv_ta_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); + + 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); + } + } + + lv_label_set_text(ext->placeholder, txt); + + placeholder_update(ta); } /** @@ -576,6 +610,7 @@ void lv_ta_set_one_line(lv_obj_t * ta, bool en) lv_page_set_scrl_fit(ta, true, true); lv_obj_set_height(ta, font_h + (style_ta->body.padding.ver + style_scrl->body.padding.ver) * 2); 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), style_ta->body.padding.hor, style_ta->body.padding.ver); } else { lv_style_t * style_ta = lv_obj_get_style(ta); @@ -583,10 +618,13 @@ void lv_ta_set_one_line(lv_obj_t * ta, bool en) ext->one_line = 0; lv_page_set_scrl_fit(ta, false, true); 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_TA_DEF_HEIGHT); lv_obj_set_pos(lv_page_get_scrl(ta), style_ta->body.padding.hor, style_ta->body.padding.ver); } + placeholder_update(ta); refr_cursor_area(ta); } @@ -675,6 +713,9 @@ void lv_ta_set_style(lv_obj_t * ta, lv_ta_style_t type, lv_style_t * style) lv_obj_refresh_ext_size(lv_page_get_scrl(ta)); /*Refresh ext. size because of cursor drawing*/ refr_cursor_area(ta); break; + case LV_TA_STYLE_PLACEHOLDER: + if(ext->placeholder) lv_label_set_style(ext->placeholder, style); + break; } } @@ -701,6 +742,21 @@ const char * lv_ta_get_text(const lv_obj_t * ta) return txt; } +/** +* Get the placeholder text of a text area +* @param ta pointer to a text area object +* @return pointer to the text +*/ +const char * lv_ta_get_placeholder_text(lv_obj_t * ta) +{ + lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); + + const char * txt = NULL; + + if(ext->placeholder) txt = lv_label_get_text(ext->label); + + return txt; +} /** * Get the label of a text area @@ -805,6 +861,9 @@ lv_style_t * lv_ta_get_style(const lv_obj_t * ta, lv_ta_style_t type) case LV_TA_STYLE_CURSOR: style = ext->cursor.style; break; + case LV_TA_STYLE_PLACEHOLDER: + if(ext->placeholder) style = lv_label_get_style(ext->placeholder); + break; default: style = NULL; break; @@ -1038,6 +1097,11 @@ static lv_res_t lv_ta_signal(lv_obj_t * ta, lv_signal_t sign, void * param) /*In not one line mode refresh the Label width because 'hpad' can modify it*/ lv_obj_set_width(ext->label, lv_obj_get_width(scrl) - 2 * style_scrl->body.padding.hor); lv_obj_set_pos(ext->label, style_scrl->body.padding.hor, style_scrl->body.padding.ver); /*Be sure the Label is in the correct position*/ + + if(ext->placeholder) { + lv_obj_set_width(ext->placeholder, lv_obj_get_width(scrl) - 2 * style_scrl->body.padding.hor); + lv_obj_set_pos(ext->placeholder, style_scrl->body.padding.hor, style_scrl->body.padding.ver); /*Be sure the placeholder is in the correct position*/ + } } lv_label_set_text(ext->label, NULL); @@ -1053,6 +1117,19 @@ static lv_res_t lv_ta_signal(lv_obj_t * ta, lv_signal_t sign, void * param) lv_obj_set_pos(ext->label, style_scrl->body.padding.hor, style_scrl->body.padding.ver); 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_t * scrl = lv_page_get_scrl(ta); + lv_style_t * style_scrl = lv_obj_get_style(scrl); + lv_obj_set_width(ext->placeholder, lv_obj_get_width(scrl) - 2 * style_scrl->body.padding.hor); + lv_obj_set_pos(ext->placeholder, style_scrl->body.padding.hor, style_scrl->body.padding.ver); + lv_label_set_text(ext->placeholder, NULL); /*Refresh the label*/ + refr_cursor_area(ta); } } @@ -1362,6 +1439,28 @@ static void refr_cursor_area(lv_obj_t * ta) lv_inv_area(&area_tmp); } +static void placeholder_update(lv_obj_t * ta) +{ + lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); + const char * ta_text; + + if(ext->placeholder == NULL) return; + + ta_text = lv_ta_get_text(ta); + + if(ta_text[0] == '\0') { + /*Be sure the main label and the placeholder has the same coordinates*/ + lv_obj_t * scrl = lv_page_get_scrl(ta); + lv_style_t * style_scrl = lv_obj_get_style(scrl); + lv_obj_set_pos(ext->placeholder, style_scrl->body.padding.hor, style_scrl->body.padding.ver); + lv_obj_set_pos(ext->label, style_scrl->body.padding.hor, style_scrl->body.padding.ver); + + lv_obj_set_width(ext->placeholder, lv_obj_get_width(scrl) - 2 * style_scrl->body.padding.hor); + 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_indev_t * click_source) { lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); diff --git a/lv_objx/lv_ta.h b/lv_objx/lv_ta.h index dd38cc857..a993459b1 100644 --- a/lv_objx/lv_ta.h +++ b/lv_objx/lv_ta.h @@ -59,6 +59,7 @@ 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 of the text area, only visible if text is an empty string*/ 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*/ @@ -80,6 +81,7 @@ enum { LV_TA_STYLE_SB, LV_TA_STYLE_EDGE_FLASH, LV_TA_STYLE_CURSOR, + LV_TA_STYLE_PLACEHOLDER, }; typedef uint8_t lv_ta_style_t; @@ -139,6 +141,13 @@ void lv_ta_del_char_forward(lv_obj_t * ta); */ void lv_ta_set_text(lv_obj_t * ta, const char * txt); +/** +* Set the placeholder text of a text area +* @param ta pointer to a text area +* @param txt pointer to the text +*/ +void lv_ta_set_placeholder_text(lv_obj_t * ta, const char * txt); + /** * Set the cursor position * @param obj pointer to a text area object @@ -251,6 +260,13 @@ void lv_ta_set_style(lv_obj_t *ta, lv_ta_style_t type, lv_style_t *style); */ const char * lv_ta_get_text(const lv_obj_t * ta); +/** +* Get the placeholder text of a text area +* @param ta pointer to a text area object +* @return pointer to the text +*/ +const char * lv_ta_get_placeholder_text(lv_obj_t * ta); + /** * Get the label of a text area * @param ta pointer to a text area object