1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

bidi: fix btnm, kb, ta, table behaviour in RTL context

This commit is contained in:
Gabor Kiss-Vamosi 2019-10-11 12:01:58 +02:00
parent c747f29664
commit 6f001958ce
7 changed files with 85 additions and 63 deletions

View File

@ -43,8 +43,10 @@ static uint32_t char_change_to_pair(uint32_t letter);
void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir)
{
printf("\nInput str: \"%s\"\n", str_in);
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in);
printf("\nInput str: \"%s\"\n", str_in);
uint32_t par_start = 0;
uint32_t par_len;
@ -68,9 +70,6 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir
str_out[par_start] = '\0';
printf("\nOutput str: \"%s\"\n", str_out);
}
lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt)
@ -86,7 +85,8 @@ lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt)
}
/*If there were no strong char earlier return with the default base dir */
return LV_BIDI_BASE_DIR_DEF;
if(LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_AUTO) return LV_BIDI_DIR_LTR;
else return LV_BIDI_BASE_DIR_DEF;
}
lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter)

View File

@ -644,7 +644,6 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
}
/*Draw the object*/
else if(mode == LV_DESIGN_DRAW_MAIN) {
ancestor_design_f(btnm, mask, mode);
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
@ -665,6 +664,10 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
lv_txt_flag_t txt_flag = LV_TXT_FLAG_NONE;
if(ext->recolor) txt_flag = LV_TXT_FLAG_RECOLOR;
#if LV_USE_BIDI
char * bidi_buf = lv_mem_alloc(64);
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(btnm);
#endif
for(btn_i = 0; btn_i < ext->btn_cnt; btn_i++, txt_i++) {
/*Search the next valid text in the map*/
@ -734,9 +737,24 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
area_tmp.x2 = area_tmp.x1 + txt_size.x;
area_tmp.y2 = area_tmp.y1 + txt_size.y;
#if LV_USE_BIDI == 0
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, -1, -1, NULL);
#else
uint32_t txt_len = strlen(ext->map_p[txt_i]) + 1;
if(txt_len > lv_mem_get_size(bidi_buf)) {
bidi_buf = lv_mem_realloc(bidi_buf, txt_len);
}
lv_bidi_process(ext->map_p[txt_i], bidi_buf, base_dir);
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, bidi_buf, txt_flag, NULL, -1, -1, NULL);
#endif
}
#if LV_USE_BIDI
lv_mem_free(bidi_buf);
#endif
}
return true;
}

View File

@ -395,7 +395,7 @@ void lv_kb_def_event_cb(lv_obj_t * kb, lv_event_t event)
/*Add the characters to the text area if set*/
if(ext->ta == NULL) return;
if(strcmp(txt, "Enter") == 0)
if(strcmp(txt, LV_SYMBOL_NEW_LINE) == 0)
lv_ta_add_char(ext->ta, '\n');
else if(strcmp(txt, LV_SYMBOL_LEFT) == 0)
lv_ta_cursor_left(ext->ta);

View File

@ -182,16 +182,7 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
/*If text is NULL then refresh */
if(text == NULL) {
#if LV_USE_BIDI == 0
lv_label_refr_text(label);
#else
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label);
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(ext->text_ori);
lv_bidi_process(ext->text_ori, ext->text, base_dir);
lv_label_refr_text(label);
#endif
return;
}
@ -208,11 +199,6 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
if(ext->text != NULL && ext->static_txt == 0) {
lv_mem_free(ext->text);
ext->text = NULL;
#if LV_USE_BIDI
lv_mem_free(ext->text_ori);
ext->text_ori = NULL;
#endif
}
ext->text = lv_mem_alloc(len);
@ -222,16 +208,8 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
#if LV_USE_BIDI == 0
strcpy(ext->text, text);
#else
ext->text_ori = lv_mem_alloc(len);
LV_ASSERT_MEM(ext->text_ori);
if(ext->text_ori == NULL) return;
strcpy(ext->text_ori, text);
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label);
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(text);
lv_bidi_process(ext->text_ori, ext->text, base_dir);
lv_bidi_process(text, ext->text, base_dir);
#endif
/*Now the text is dynamically allocated*/
ext->static_txt = 0;
@ -622,7 +600,10 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
lv_label_align_t align = lv_label_get_align(label);
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
/*If the width will be expanded the set the max length to very big */
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
@ -654,12 +635,12 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
if(index != line_start) x += style->text.letter_space;
if(ext->align == LV_LABEL_ALIGN_CENTER) {
if(align == LV_LABEL_ALIGN_CENTER) {
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) / 2 - line_w / 2;
} else if(ext->align == LV_LABEL_ALIGN_RIGHT) {
} else if(align == LV_LABEL_ALIGN_RIGHT) {
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);
@ -694,7 +675,10 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
lv_label_align_t align = lv_label_get_align(label);
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
/*If the width will be expanded set the max length to very big */
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
@ -713,11 +697,16 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
/*Calculate the x coordinate*/
lv_coord_t x = 0;
if(ext->align == LV_LABEL_ALIGN_CENTER) {
if(align == LV_LABEL_ALIGN_CENTER) {
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) / 2 - line_w / 2;
}
else if(align == LV_LABEL_ALIGN_RIGHT) {
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;
}
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
@ -1192,11 +1181,12 @@ static void lv_label_refr_text(lv_obj_t * label)
/*In roll inf. mode keep the size but start offset animations*/
else if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
#if LV_USE_ANIMATION
lv_label_align_t align = lv_label_get_align(label);
lv_anim_t anim;
anim.var = label;
anim.repeat = 1;
anim.playback = 0;
anim.start = 0;
anim.act_time = -(((lv_font_get_glyph_width(style->text.font, ' ', ' ') + style->text.letter_space) * 1000) /
ext->anim_speed) *
LV_LABEL_WAIT_CHAR_COUNT;
@ -1207,7 +1197,14 @@ static void lv_label_refr_text(lv_obj_t * label)
bool hor_anim = false;
if(size.x > lv_obj_get_width(label)) {
anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
if(align == LV_LABEL_ALIGN_RIGHT) {
anim.end = 0;
anim.start = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
} else {
anim.start = 0;
anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
}
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_x;
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
lv_anim_create(&anim);
@ -1219,7 +1216,14 @@ static void lv_label_refr_text(lv_obj_t * label)
}
if(size.y > lv_obj_get_height(label) && hor_anim == false) {
anim.end = -size.y - (lv_font_get_line_height(font));
if(align == LV_LABEL_ALIGN_RIGHT) {
anim.end = 0;
anim.start = -size.y - (lv_font_get_line_height(font));
} else {
anim.start = 0;
anim.end = -size.y - (lv_font_get_line_height(font));
}
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_y;
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
lv_anim_create(&anim);

View File

@ -71,10 +71,6 @@ typedef struct
/*New data for this type */
char * text; /*Text of the label*/
#if LV_USE_BIDI
char * text_ori; /*The original text. With BiDi `text` stores the characters in "bidi" ordered text*/
#endif
union
{
char * tmp_ptr; /* Pointer to the allocated memory containing the character which are replaced by dots (Handled

View File

@ -1850,53 +1850,53 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_
lv_indev_get_vect(click_source, &vect_act);
if(point_act.x < 0 || point_act.y < 0) return; /*Ignore event from keypad*/
lv_point_t relative_position;
relative_position.x = point_act.x - label_coords.x1;
relative_position.y = point_act.y - label_coords.y1;
lv_point_t rel_pos;
rel_pos.x = point_act.x - label_coords.x1;
rel_pos.y = point_act.y - label_coords.y1;
lv_coord_t label_width = lv_obj_get_width(ext->label);
uint16_t index_of_char_at_position;
uint16_t char_id_at_click;
#if LV_LABEL_TEXT_SEL
lv_label_ext_t * ext_label = lv_obj_get_ext_attr(ext->label);
bool click_outside_label;
/*Check if the click happened on the left side of the area outside the label*/
if(relative_position.x < 0) {
index_of_char_at_position = 0;
if(rel_pos.x < 0) {
char_id_at_click = 0;
click_outside_label = true;
}
/*Check if the click happened on the right side of the area outside the label*/
else if(relative_position.x >= label_width) {
index_of_char_at_position = LV_TA_CURSOR_LAST;
else if(rel_pos.x >= label_width) {
char_id_at_click = LV_TA_CURSOR_LAST;
click_outside_label = true;
} else {
index_of_char_at_position = lv_label_get_letter_on(ext->label, &relative_position);
click_outside_label = !lv_label_is_char_under_pos(ext->label, &relative_position);
char_id_at_click = lv_label_get_letter_on(ext->label, &rel_pos);
click_outside_label = !lv_label_is_char_under_pos(ext->label, &rel_pos);
}
if(ext->text_sel_en) {
if(!ext->text_sel_in_prog && !click_outside_label && sign == LV_SIGNAL_PRESSED) {
/*Input device just went down. Store the selection start position*/
ext->tmp_sel_start = index_of_char_at_position;
ext->tmp_sel_start = char_id_at_click;
ext->tmp_sel_end = LV_LABEL_TEXT_SEL_OFF;
ext->text_sel_in_prog = 1;
lv_obj_set_drag(lv_page_get_scrl(ta), false);
} else if(ext->text_sel_in_prog && sign == LV_SIGNAL_PRESSING) {
/*Input device may be moving. Store the end position */
ext->tmp_sel_end = index_of_char_at_position;
ext->tmp_sel_end = char_id_at_click;
} else if(ext->text_sel_in_prog && (sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED)) {
/*Input device is released. Check if anything was selected.*/
lv_obj_set_drag(lv_page_get_scrl(ta), true);
}
}
if(ext->text_sel_in_prog || sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, index_of_char_at_position);
if(ext->text_sel_in_prog || sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, char_id_at_click);
if(ext->text_sel_in_prog) {
/*If the selected area has changed then update the real values and*/
/*invalidate the text area.*/
/*Invalidate the text area.*/
if(ext->tmp_sel_start > ext->tmp_sel_end) {
if(ext_label->txt_sel_start != ext->tmp_sel_end || ext_label->txt_sel_end != ext->tmp_sel_start) {
ext_label->txt_sel_start = ext->tmp_sel_end;
@ -1923,17 +1923,17 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_
}
#else
/*Check if the click happened on the left side of the area outside the label*/
if(relative_position.x < 0) {
index_of_char_at_position = 0;
if(rel_pos.x < 0) {
char_id_at_click = 0;
}
/*Check if the click happened on the right side of the area outside the label*/
else if(relative_position.x >= label_width) {
index_of_char_at_position = LV_TA_CURSOR_LAST;
else if(rel_pos.x >= label_width) {
char_id_at_click = LV_TA_CURSOR_LAST;
} else {
index_of_char_at_position = lv_label_get_letter_on(ext->label, &relative_position);
char_id_at_click = lv_label_get_letter_on(ext->label, &rel_pos);
}
if(sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, index_of_char_at_position);
if(sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, char_id_at_click);
#endif
}

View File

@ -151,7 +151,11 @@ void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const
}
/*Initialize the format byte*/
else {
format.s.align = LV_LABEL_ALIGN_LEFT;
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(table);
if(base_dir == LV_BIDI_DIR_LTR) format.s.align = LV_LABEL_ALIGN_LEFT;
else if(base_dir == LV_BIDI_DIR_RTL) format.s.align = LV_LABEL_ALIGN_RIGHT;
else if(base_dir == LV_BIDI_DIR_AUTO) format.s.align = lv_bidi_detect_base_dir(txt);
format.s.right_merge = 0;
format.s.type = 0;
format.s.crop = 0;