From e18e14f7798839b5ff6e1acff1844c603becabf7 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 25 Sep 2018 16:21:31 +0200 Subject: [PATCH] add lv_ta_set_text_align() --- lv_draw/lv_draw_label.c | 10 ++-- lv_misc/lv_txt.c | 10 ++-- lv_misc/lv_txt.h | 4 +- lv_objx/lv_label.c | 27 ++++------- lv_objx/lv_label.h | 1 + lv_objx/lv_ta.c | 105 +++++++++++++++++++++++++++------------- lv_objx/lv_ta.h | 9 ++++ 7 files changed, 104 insertions(+), 62 deletions(-) diff --git a/lv_draw/lv_draw_label.c b/lv_draw/lv_draw_label.c index a7979113e..86e006c83 100644 --- a/lv_draw/lv_draw_label.c +++ b/lv_draw/lv_draw_label.c @@ -60,8 +60,10 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st const lv_font_t * font = style->text.font; lv_coord_t w; if((flag & LV_TXT_FLAG_EXPAND) == 0) { + /*Normally use the label's width as width*/ w = lv_area_get_width(coords); } else { + /*If EXAPND is enabled then not limit the text's width to the object's width*/ lv_point_t p; lv_txt_get_size(&p, txt, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, flag); w = p.x; @@ -81,14 +83,14 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); - pos.x += (w - line_width) / 2; + pos.x += (lv_area_get_width(coords) - line_width) / 2; } /*Align to the right*/ else if(flag & LV_TXT_FLAG_RIGHT) { line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); - pos.x += w - line_width; + pos.x += lv_area_get_width(coords) - line_width; } @@ -180,14 +182,14 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); - pos.x += (w - line_width) / 2; + pos.x += (lv_area_get_width(coords) - line_width) / 2; } /*Align to the right*/ else if(flag & LV_TXT_FLAG_RIGHT) { line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); - pos.x += w - line_width; + pos.x += lv_area_get_width(coords) - line_width; } /*Go the next line position*/ diff --git a/lv_misc/lv_txt.c b/lv_misc/lv_txt.c index 295a6d49b..8dc314cdb 100644 --- a/lv_misc/lv_txt.c +++ b/lv_misc/lv_txt.c @@ -57,7 +57,7 @@ uint32_t (*lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_utf8; uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_conv_wc; uint32_t (*lv_txt_encoded_next)(const char * , uint32_t *) = lv_txt_utf8_next; uint32_t (*lv_txt_encoded_prev)(const char * , uint32_t * ) = lv_txt_utf8_prev; -uint32_t (*txt_encoded_get_byte_id)(const char * , uint32_t) = lv_txt_utf8_get_byte_id; +uint32_t (*lv_txt_encoded_get_byte_id)(const char * , uint32_t) = lv_txt_utf8_get_byte_id; uint32_t (*lv_encoded_get_char_id)(const char * , uint32_t) = lv_txt_utf8_get_char_id; uint32_t (*lv_txt_get_encoded_length)(const char * ) = lv_txt_utf8_get_length; #else @@ -66,7 +66,7 @@ uint32_t (*lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_ascii; uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_ascii_conv_wc; uint32_t (*lv_txt_encoded_next)(const char * , uint32_t *) = lv_txt_ascii_next; uint32_t (*lv_txt_encoded_prev)(const char * , uint32_t * ) = lv_txt_ascii_prev; -uint32_t (*txt_encoded_get_byte_id)(const char * , uint32_t) = lv_txt_ascii_get_byte_id; +uint32_t (*lv_txt_encoded_get_byte_id)(const char * , uint32_t) = lv_txt_ascii_get_byte_id; uint32_t (*lv_encoded_get_char_id)(const char * , uint32_t) = lv_txt_ascii_get_char_id; uint32_t (*lv_txt_get_encoded_length)(const char * ) = lv_txt_ascii_get_length; #endif @@ -296,7 +296,7 @@ void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt) uint32_t ins_len = strlen(ins_txt); uint32_t new_len = ins_len + old_len; #if LV_TXT_UTF8 != 0 - pos = txt_encoded_get_byte_id(txt_buf, pos); /*Convert to byte index instead of letter index*/ + pos = lv_txt_encoded_get_byte_id(txt_buf, pos); /*Convert to byte index instead of letter index*/ #endif /*Copy the second part into the end to make place to text to insert*/ uint32_t i; @@ -319,8 +319,8 @@ void lv_txt_cut(char * txt, uint32_t pos, uint32_t len) uint32_t old_len = strlen(txt); #if LV_TXT_UTF8 != 0 - pos = txt_encoded_get_byte_id(txt, pos); /*Convert to byte index instead of letter index*/ - len = txt_encoded_get_byte_id(&txt[pos], len); + pos = lv_txt_encoded_get_byte_id(txt, pos); /*Convert to byte index instead of letter index*/ + len = lv_txt_encoded_get_byte_id(&txt[pos], len); #endif /*Copy the second part into the end to make place to text to insert*/ diff --git a/lv_misc/lv_txt.h b/lv_misc/lv_txt.h index 91a90b9ba..659c72f8a 100644 --- a/lv_misc/lv_txt.h +++ b/lv_misc/lv_txt.h @@ -36,7 +36,7 @@ enum { LV_TXT_FLAG_NONE = 0x00, LV_TXT_FLAG_RECOLOR = 0x01, /*Enable parsing of recolor command*/ - LV_TXT_FLAG_EXPAND = 0x02, /*Ignore width (Used by the library)*/ + LV_TXT_FLAG_EXPAND = 0x02, /*Ignore width to avoid automatic word wrapping*/ LV_TXT_FLAG_CENTER = 0x04, /*Align the text to the middle*/ LV_TXT_FLAG_RIGHT = 0x08, /*Align the text to the right*/ }; @@ -168,7 +168,7 @@ extern uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *); * @param enc_id letter index * @return byte index of the 'enc_id'th letter */ -extern uint32_t (*txt_encoded_get_byte_id)(const char *, uint32_t); +extern uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t); /** * Convert a byte index (in an encoded text) to character index. diff --git a/lv_objx/lv_label.c b/lv_objx/lv_label.c index a8d9c2502..f1694d564 100644 --- a/lv_objx/lv_label.c +++ b/lv_objx/lv_label.c @@ -252,7 +252,7 @@ void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode) ext->offset.x = 0; ext->offset.y = 0; - if(long_mode == LV_LABEL_LONG_ROLL) ext->expand = 1; + if(long_mode == LV_LABEL_LONG_ROLL || long_mode == LV_LABEL_LONG_CROP) ext->expand = 1; else ext->expand = 0; /*Restore the character under the dots*/ @@ -428,7 +428,7 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t max_w = LV_COORD_MAX; } - index = txt_encoded_get_byte_id(txt, index); + index = lv_txt_encoded_get_byte_id(txt, index); /*Search the line of the index letter */; while(txt[new_line_start] != '\0') { @@ -474,7 +474,8 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t lv_coord_t line_w; line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); - x += lv_obj_get_width(label) - line_w; + + x += lv_obj_get_width(label) - line_w; } pos->x = x; @@ -674,18 +675,6 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER; if(ext->align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT; - /* In ROLL mode if the text is shorter then the label's width and - * the text is aligned to the middle then clear the EXPAND flag. - * Due to this `lv_draw_label` can align the text to the middle */ - if(ext->long_mode == LV_LABEL_LONG_ROLL && ext->align == LV_LABEL_ALIGN_CENTER) { - lv_point_t size; - lv_txt_get_size(&size, ext->text, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX ,flag); - if(size.x < lv_obj_get_width(label)) { - flag &= ~LV_TXT_FLAG_EXPAND; - } - } - - lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset); } return true; @@ -877,7 +866,7 @@ static void lv_label_refr_text(lv_obj_t * label) #else /*Save letters under the dots and replace them with dots*/ uint32_t i; - uint32_t byte_id = txt_encoded_get_byte_id(ext->text, letter_id); + uint32_t byte_id = lv_txt_encoded_get_byte_id(ext->text, letter_id); uint32_t byte_id_ori = byte_id; uint8_t len = 0; for(i = 0; i <= LV_LABEL_DOT_NUM; i++) { @@ -902,6 +891,10 @@ static void lv_label_refr_text(lv_obj_t * label) else if(ext->long_mode == LV_LABEL_LONG_BREAK) { lv_obj_set_height(label, size.y); } + /*Do not set the size in Clip mode*/ + else if(ext->long_mode == LV_LABEL_LONG_CROP) { + /*Do nothing*/ + } lv_obj_invalidate(label); @@ -919,7 +912,7 @@ static void lv_label_revert_dots(lv_obj_t * label) } #else uint32_t letter_i = ext->dot_end - LV_LABEL_DOT_NUM; - uint32_t byte_i = txt_encoded_get_byte_id(ext->text, letter_i); + uint32_t byte_i = lv_txt_encoded_get_byte_id(ext->text, letter_i); /*Restore the characters*/ uint8_t i = 0; diff --git a/lv_objx/lv_label.h b/lv_objx/lv_label.h index b8d863db8..6bdcb5cf3 100644 --- a/lv_objx/lv_label.h +++ b/lv_objx/lv_label.h @@ -44,6 +44,7 @@ enum LV_LABEL_LONG_SCROLL, /*Expand the object size and scroll the text on the parent (move the label object)*/ LV_LABEL_LONG_DOT, /*Keep the size and write dots at the end if the text is too long*/ LV_LABEL_LONG_ROLL, /*Keep the size and roll the text infinitely*/ + LV_LABEL_LONG_CROP, /*Keep the size and crop the text out of it*/ }; typedef uint8_t lv_label_long_mode_t; diff --git a/lv_objx/lv_ta.c b/lv_objx/lv_ta.c index 2aec1e739..23f940580 100644 --- a/lv_objx/lv_ta.c +++ b/lv_objx/lv_ta.c @@ -322,7 +322,7 @@ void lv_ta_del_char(lv_obj_t * ta) #if LV_TXT_UTF8 == 0 lv_txt_cut(ext->pwd_tmp, ext->cursor.pos - 1, 1); #else - uint32_t byte_pos = txt_encoded_get_byte_id(ext->pwd_tmp, ext->cursor.pos - 1); + uint32_t byte_pos = lv_txt_encoded_get_byte_id(ext->pwd_tmp, ext->cursor.pos - 1); lv_txt_cut(ext->pwd_tmp, ext->cursor.pos - 1, lv_txt_encoded_size(&label_txt[byte_pos])); #endif ext->pwd_tmp = lv_mem_realloc(ext->pwd_tmp, strlen(ext->pwd_tmp) + 1); @@ -534,7 +534,7 @@ void lv_ta_set_one_line(lv_obj_t * ta, bool en) lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); if(ext->one_line == en) return; - if(en != false) { + if(en) { lv_style_t * style_ta = lv_obj_get_style(ta); lv_style_t * style_scrl = lv_obj_get_style(lv_page_get_scrl(ta)); lv_style_t * style_label = lv_obj_get_style(ext->label); @@ -556,6 +556,40 @@ void lv_ta_set_one_line(lv_obj_t * ta, bool en) } } +/** + * Set the alignment of the text area. + * In one line mode the text can be scrolled only with `LV_LABEL_ALIGN_LEFT`. + * This function should be called if the size of text area changes. + * @param ta pointer to a text are object + * @param align the desired alignment from `lv_label_align_t`. (LV_LABEL_ALIGN_LEFT/CENTER/RIGHT) + */ +void lv_ta_set_text_align(lv_obj_t * ta, lv_label_align_t align) +{ + lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); + lv_obj_t * label = lv_ta_get_label(ta); + if(!ext->one_line) { + lv_label_set_align(label, 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_fit(ta, true, false); + lv_label_set_align(label, 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_fit(ta, false, false); + lv_page_set_scrl_width(ta, 1); /*To refresh the scrollable's width*/ + lv_label_set_align(label, align); + + lv_style_t * bg_style = lv_ta_get_style(ta, LV_TA_STYLE_BG); + lv_obj_set_width(label, lv_obj_get_width(ta) - 2 * bg_style->body.padding.hor); + } + + } +} /** * Set a list of characters. Only these characters will be accepted by the text area @@ -868,22 +902,22 @@ static bool lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t * mask, lv_ } else if(mode == LV_DESIGN_DRAW_POST) { scrl_design(scrl, mask, mode); - /*Draw the cursor too*/ + /*Draw the cursor*/ lv_obj_t * ta = lv_obj_get_parent(scrl); - lv_ta_ext_t * ta_ext = lv_obj_get_ext_attr(ta); - lv_style_t * label_style = lv_obj_get_style(ta_ext->label); + lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); + lv_style_t * label_style = lv_obj_get_style(ext->label); lv_opa_t opa_scale = lv_obj_get_opa_scale(ta); - if(ta_ext->cursor.type == LV_CURSOR_NONE || - (ta_ext->cursor.type & LV_CURSOR_HIDDEN) || - ta_ext->cursor.state == 0 || + if(ext->cursor.type == LV_CURSOR_NONE || + (ext->cursor.type & LV_CURSOR_HIDDEN) || + ext->cursor.state == 0 || label_style->body.opa == LV_OPA_TRANSP) { return true; /*The cursor is not visible now*/ } lv_style_t cur_style; - if(ta_ext->cursor.style != NULL) { - lv_style_copy(&cur_style, ta_ext->cursor.style); + if(ext->cursor.style != NULL) { + lv_style_copy(&cur_style, ext->cursor.style); } else { /*If cursor style is not specified then use the modified label style */ lv_style_copy(&cur_style, label_style); @@ -904,10 +938,10 @@ static bool lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t * mask, lv_ } uint16_t cur_pos = lv_ta_get_cursor_pos(ta); - const char * txt = lv_label_get_text(ta_ext->label); + const char * txt = lv_label_get_text(ext->label); uint32_t byte_pos; #if LV_TXT_UTF8 != 0 - byte_pos = txt_encoded_get_byte_id(txt, cur_pos); + byte_pos = lv_txt_encoded_get_byte_id(txt, cur_pos); #else byte_pos = cur_pos; #endif @@ -923,10 +957,13 @@ static bool lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t * mask, lv_ } lv_point_t letter_pos; - lv_label_get_letter_pos(ta_ext->label, cur_pos, &letter_pos); + lv_label_get_letter_pos(ext->label, cur_pos, &letter_pos); + + /*In one line mode the cursor can be only in the first line */ + if(ext->one_line && letter_pos.y > letter_h) return true; /*If the cursor is out of the text (most right) draw it to the next line*/ - if(letter_pos.x + ta_ext->label->coords.x1 + letter_w > ta_ext->label->coords.x2 && ta_ext->one_line == 0) { + if(letter_pos.x + ext->label->coords.x1 + letter_w > ext->label->coords.x2 && ext->one_line == 0) { letter_pos.x = 0; letter_pos.y += letter_h + label_style->text.line_space; @@ -944,17 +981,17 @@ static bool lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t * mask, lv_ /*Draw he cursor according to the type*/ lv_area_t cur_area; - if(ta_ext->cursor.type == LV_CURSOR_LINE) { - cur_area.x1 = letter_pos.x + ta_ext->label->coords.x1 + cur_style.body.padding.hor - (cur_style.line.width >> 1) - (cur_style.line.width & 0x1); - cur_area.y1 = letter_pos.y + ta_ext->label->coords.y1 + cur_style.body.padding.ver; - cur_area.x2 = letter_pos.x + ta_ext->label->coords.x1 + cur_style.body.padding.hor + (cur_style.line.width >> 1); - cur_area.y2 = letter_pos.y + ta_ext->label->coords.y1 + cur_style.body.padding.ver + letter_h; + if(ext->cursor.type == LV_CURSOR_LINE) { + cur_area.x1 = letter_pos.x + ext->label->coords.x1 + cur_style.body.padding.hor - (cur_style.line.width >> 1) - (cur_style.line.width & 0x1); + cur_area.y1 = letter_pos.y + ext->label->coords.y1 + cur_style.body.padding.ver; + cur_area.x2 = letter_pos.x + ext->label->coords.x1 + cur_style.body.padding.hor + (cur_style.line.width >> 1); + cur_area.y2 = letter_pos.y + ext->label->coords.y1 + cur_style.body.padding.ver + letter_h; lv_draw_rect(&cur_area, mask, &cur_style, opa_scale); - } else if(ta_ext->cursor.type == LV_CURSOR_BLOCK) { - cur_area.x1 = letter_pos.x + ta_ext->label->coords.x1 - cur_style.body.padding.hor; - cur_area.y1 = letter_pos.y + ta_ext->label->coords.y1 - cur_style.body.padding.ver; - cur_area.x2 = letter_pos.x + ta_ext->label->coords.x1 + cur_style.body.padding.hor + letter_w; - cur_area.y2 = letter_pos.y + ta_ext->label->coords.y1 + cur_style.body.padding.ver + letter_h; + } else if(ext->cursor.type == LV_CURSOR_BLOCK) { + cur_area.x1 = letter_pos.x + ext->label->coords.x1 - cur_style.body.padding.hor; + cur_area.y1 = letter_pos.y + ext->label->coords.y1 - cur_style.body.padding.ver; + cur_area.x2 = letter_pos.x + ext->label->coords.x1 + cur_style.body.padding.hor + letter_w; + cur_area.y2 = letter_pos.y + ext->label->coords.y1 + cur_style.body.padding.ver + letter_h; lv_draw_rect(&cur_area, mask, &cur_style, opa_scale); @@ -971,20 +1008,20 @@ static bool lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t * mask, lv_ cur_area.y1 += cur_style.body.padding.ver; lv_draw_label(&cur_area, mask, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, 0); - } else if(ta_ext->cursor.type == LV_CURSOR_OUTLINE) { - cur_area.x1 = letter_pos.x + ta_ext->label->coords.x1 - cur_style.body.padding.hor; - cur_area.y1 = letter_pos.y + ta_ext->label->coords.y1 - cur_style.body.padding.ver; - cur_area.x2 = letter_pos.x + ta_ext->label->coords.x1 + cur_style.body.padding.hor + letter_w; - cur_area.y2 = letter_pos.y + ta_ext->label->coords.y1 + cur_style.body.padding.ver + letter_h; + } else if(ext->cursor.type == LV_CURSOR_OUTLINE) { + cur_area.x1 = letter_pos.x + ext->label->coords.x1 - cur_style.body.padding.hor; + cur_area.y1 = letter_pos.y + ext->label->coords.y1 - cur_style.body.padding.ver; + cur_area.x2 = letter_pos.x + ext->label->coords.x1 + cur_style.body.padding.hor + letter_w; + cur_area.y2 = letter_pos.y + ext->label->coords.y1 + cur_style.body.padding.ver + letter_h; cur_style.body.empty = 1; if(cur_style.body.border.width == 0) cur_style.body.border.width = 1; /*Be sure the border will be drawn*/ lv_draw_rect(&cur_area, mask, &cur_style, opa_scale); - } else if(ta_ext->cursor.type == LV_CURSOR_UNDERLINE) { - cur_area.x1 = letter_pos.x + ta_ext->label->coords.x1 + cur_style.body.padding.hor; - cur_area.y1 = letter_pos.y + ta_ext->label->coords.y1 + cur_style.body.padding.ver + letter_h - (cur_style.line.width >> 1); - cur_area.x2 = letter_pos.x + ta_ext->label->coords.x1 + cur_style.body.padding.hor + letter_w; - cur_area.y2 = letter_pos.y + ta_ext->label->coords.y1 + cur_style.body.padding.ver + letter_h + (cur_style.line.width >> 1) + (cur_style.line.width & 0x1); + } else if(ext->cursor.type == LV_CURSOR_UNDERLINE) { + cur_area.x1 = letter_pos.x + ext->label->coords.x1 + cur_style.body.padding.hor; + cur_area.y1 = letter_pos.y + ext->label->coords.y1 + cur_style.body.padding.ver + letter_h - (cur_style.line.width >> 1); + cur_area.x2 = letter_pos.x + ext->label->coords.x1 + cur_style.body.padding.hor + letter_w; + cur_area.y2 = letter_pos.y + ext->label->coords.y1 + cur_style.body.padding.ver + letter_h + (cur_style.line.width >> 1) + (cur_style.line.width & 0x1); lv_draw_rect(&cur_area, mask, &cur_style, opa_scale); } diff --git a/lv_objx/lv_ta.h b/lv_objx/lv_ta.h index a0a93d9b1..970c7dff3 100644 --- a/lv_objx/lv_ta.h +++ b/lv_objx/lv_ta.h @@ -160,6 +160,15 @@ void lv_ta_set_pwd_mode(lv_obj_t * ta, bool pwd_en); */ void lv_ta_set_one_line(lv_obj_t * ta, bool en); +/** + * Set the alignment of the text area. + * In one line mode the text can be scrolled only with `LV_LABEL_ALIGN_LEFT`. + * This function should be called if the size of text area changes. + * @param ta pointer to a text are object + * @param align the desired alignment from `lv_label_align_t`. (LV_LABEL_ALIGN_LEFT/CENTER/RIGHT) + */ +void lv_ta_set_text_align(lv_obj_t * ta, lv_label_align_t align); + /** * Set a list of characters. Only these characters will be accepted by the text area * @param ta pointer to Text Area