improve edit/mledit

This commit is contained in:
lixianjing 2022-03-22 15:52:47 +08:00
parent afb8a40dba
commit 306d6476e4
6 changed files with 172 additions and 41 deletions

View File

@ -2,6 +2,7 @@
2022/03/22
* 修复软键盘让窗口上移后再次弹出软键盘导致窗口动画不正常的问题(感谢智明提供补丁)
* 修复在 text_edit 在点击和拖拽的时候执行 layout 导致的卡顿问题以及修复翻页不正常的问题(感谢智明提供补丁)
2022/03/21
* 完善3or5keys文档感谢雨欣提供补丁

View File

@ -98,6 +98,7 @@ typedef struct _text_edit_impl_t {
uint32_t line_height;
uint32_t last_line_number;
uint32_t last_row_number;
uint32_t caret_line_index;
text_layout_info_t layout_info;
bool_t preedit;
@ -121,6 +122,7 @@ typedef struct _text_edit_impl_t {
#define DECL_IMPL(te) text_edit_impl_t* impl = (text_edit_impl_t*)(te)
static ret_t text_edit_notify(text_edit_t* text_edit);
static bool_t text_edit_is_need_layout(text_edit_t* text_edit);
static int32_t text_edit_calc_x(text_edit_t* text_edit, line_info_t* iter);
static align_h_t widget_get_text_align_h(widget_t* widget) {
@ -143,8 +145,8 @@ static ret_t widget_get_text_layout_info(widget_t* widget, text_layout_info_t* i
info->widget_w = widget->w;
info->widget_h = widget->h;
info->virtual_w = widget->w;
info->virtual_h = widget->h;
info->virtual_w = tk_max(info->virtual_w, widget->w);
info->virtual_h = tk_max(info->virtual_h, widget->h);
TEXT_EDIT_GET_WIDGET_MARGIN(widget, style, info->margin_l, LEFT);
TEXT_EDIT_GET_WIDGET_MARGIN(widget, style, info->margin_r, RIGHT);
@ -208,7 +210,7 @@ static ret_t rows_destroy(rows_t* rows) {
}
static ret_t text_edit_set_caret_pos(text_edit_impl_t* impl, uint32_t x, uint32_t y,
uint32_t font_size) {
uint32_t font_size, uint32_t line_number) {
text_layout_info_t* layout_info = &(impl->layout_info);
uint32_t caret_top = layout_info->margin_t + y;
uint32_t caret_bottom = layout_info->margin_t + y + font_size;
@ -222,6 +224,7 @@ static ret_t text_edit_set_caret_pos(text_edit_impl_t* impl, uint32_t x, uint32_
impl->caret.x = x;
impl->caret.y = y;
impl->caret_line_index = line_number;
if (!impl->lock_scrollbar_value) {
if (view_top > caret_top) {
@ -320,7 +323,7 @@ static row_info_t* text_edit_single_line_layout_line(text_edit_t* text_edit, uin
caret_x = (layout_info->w - text_w) / 2 + caret_text_w;
}
}
text_edit_set_caret_pos(impl, caret_x, y, c->font_size);
text_edit_set_caret_pos(impl, caret_x, y, c->font_size, line_index);
return row;
}
@ -331,13 +334,13 @@ static row_info_t* text_edit_multi_line_layout_line(text_edit_t* text_edit, uint
uint32_t x = 0;
DECL_IMPL(text_edit);
wchar_t last_char = 0;
point_t caret = {-1, -1};
canvas_t* c = GET_CANVAS(text_edit);
wstr_t* text = &(text_edit->widget->text);
STB_TexteditState* state = &(impl->state);
row_info_t* row = impl->rows->row + row_num;
uint32_t line_height = impl->line_height;
uint32_t y = line_index * line_height;
uint32_t y0 = y;
uint32_t offset0 = offset;
uint32_t last_breakable_i = 0;
uint32_t last_breakable_x = 0;
@ -354,7 +357,8 @@ static row_info_t* text_edit_multi_line_layout_line(text_edit_t* text_edit, uint
uint32_t char_w = canvas_measure_text(c, p, 1) + CHAR_SPACING;
if (i == state->cursor) {
text_edit_set_caret_pos(impl, x, y, c->font_size);
caret.x = x;
caret.y = y;
}
last_char = *p;
@ -393,6 +397,10 @@ static row_info_t* text_edit_multi_line_layout_line(text_edit_t* text_edit, uint
y += line_height;
offset = i;
line_index++;
if (state->cursor == i) {
caret.x = 0;
caret.y = y;
}
continue;
}
@ -421,11 +429,17 @@ static row_info_t* text_edit_multi_line_layout_line(text_edit_t* text_edit, uint
if (i == state->cursor && state->cursor == text->size) {
if (last_char == STB_TEXTEDIT_NEWLINE) {
text_edit_set_caret_pos(impl, 0, y + line_height, c->font_size);
caret.x = 0;
caret.y = y + line_height;
} else {
text_edit_set_caret_pos(impl, x, y, c->font_size);
caret.x = x;
caret.y = y;
}
}
if (caret.x >= 0 && caret.y >= 0) {
/* 计算好了再统一修改光标坐标,以免多次修改导致滚动条的位置突变 */
text_edit_set_caret_pos(impl, caret.x, caret.y, c->font_size, line_index);
}
last_line = (line_info_t*)darray_get(&row->info, row->line_num - 1);
memset(last_line, 0x00, sizeof(line_info_t));
@ -434,7 +448,7 @@ static row_info_t* text_edit_multi_line_layout_line(text_edit_t* text_edit, uint
last_line->length = i - offset;
row->length = i - offset0;
layout_info->virtual_h = tk_max(y0, layout_info->widget_h);
layout_info->virtual_h = tk_max(y + line_height, layout_info->widget_h);
return row;
}
@ -711,8 +725,8 @@ static ret_t text_edit_paint_line(text_edit_t* text_edit, canvas_t* c, line_info
}
if (chr != STB_TEXTEDIT_NEWLINE) {
uint32_t rx = x - layout_info->ox;
uint32_t ry = y - layout_info->oy;
xy_t rx = x - layout_info->ox;
xy_t ry = y - layout_info->oy;
if (selected || preedit) {
color_t select_bg_color = style_get_color(style, STYLE_ID_SELECTED_BG_COLOR, white);
@ -844,17 +858,11 @@ ret_t text_edit_paint(text_edit_t* text_edit, canvas_t* c) {
text_edit_layout(text_edit);
impl->is_first_time_layout = FALSE;
impl->font_name = style_get_str(style, STYLE_ID_FONT_NAME, "default");
impl->font_size = style_get_int(style, STYLE_ID_FONT_SIZE, TK_DEFAULT_FONT_SIZE);
impl->font_name = system_info_fix_font_name(style_get_str(style, STYLE_ID_FONT_NAME, NULL));
} else {
const char* font_name = style_get_str(style, STYLE_ID_FONT_NAME, "default");
int32_t font_size = style_get_int(style, STYLE_ID_FONT_SIZE, TK_DEFAULT_FONT_SIZE);
if (!tk_str_eq(font_name, impl->font_name) || font_size != impl->font_size) {
if (text_edit_is_need_layout(text_edit)) {
text_edit_layout(text_edit);
impl->font_name = font_name;
impl->font_size = font_size;
}
}
@ -1119,6 +1127,74 @@ static point_t text_edit_normalize_point(text_edit_t* text_edit, xy_t x, xy_t y)
return point;
}
static bool_t text_edit_is_need_layout(text_edit_t* text_edit) {
DECL_IMPL(text_edit);
style_t* style = text_edit->widget->astyle;
uint16_t font_size = style_get_int(style, STYLE_ID_FONT_SIZE, TK_DEFAULT_FONT_SIZE);
const char* font_name = system_info_fix_font_name(style_get_str(style, STYLE_ID_FONT_NAME, NULL));
if (!tk_str_eq(font_name, impl->font_name) || font_size != impl->font_size) {
impl->font_name = font_name;
impl->font_size = font_size;
return TRUE;
}
return FALSE;
}
static ret_t text_edit_update_caret_pos(text_edit_t* text_edit) {
uint32_t i = 0;
uint32_t j = 0;
uint32_t k = 0;
uint32_t y = 0;
DECL_IMPL(text_edit);
uint32_t line_index = 0;
rows_t* rows = impl->rows;
bool_t is_setting = FALSE;
canvas_t* c = GET_CANVAS(text_edit);
uint32_t font_size = impl->font_size;
uint32_t line_height = impl->line_height;
wstr_t* text = &(text_edit->widget->text);
canvas_set_font(c, impl->font_name, font_size);
for (i = 0; i < rows->size; i++) {
row_info_t* row = rows->row + i;
for (j = 0; j < row->line_num; j++, y+=line_height, line_index++) {
line_info_t* line = (line_info_t*)darray_get(&row->info, j);
uint32_t line_offset_begin = line->offset;
uint32_t line_offset_end = line->offset + line->length;
if ((line_offset_begin <= impl->state.cursor && impl->state.cursor < line_offset_end) ||
(j + 1 == row->line_num && impl->state.cursor == line_offset_end)) {
uint32_t x = line->x;
wchar_t last_char = 0;
wchar_t* p = text->str + line_offset_begin;
uint32_t offset = impl->state.cursor - line_offset_begin;
for (k = 0; k < line->length; k++, p++) {
if (offset == k) {
break;
}
x += (canvas_measure_text(c, p, 1) + CHAR_SPACING);
last_char = *p;
}
is_setting = TRUE;
if (last_char == STB_TEXTEDIT_NEWLINE) {
text_edit_set_caret_pos(impl, 0, y + line_height, c->font_size, line_index);
} else {
text_edit_set_caret_pos(impl, x, y, c->font_size, line_index);
}
break;
}
}
if (is_setting) {
break;
}
}
text_edit_fix_oy(impl);
text_edit_notify(text_edit);
return RET_OK;
}
ret_t text_edit_click(text_edit_t* text_edit, xy_t x, xy_t y) {
point_t point;
DECL_IMPL(text_edit);
@ -1127,7 +1203,12 @@ ret_t text_edit_click(text_edit_t* text_edit, xy_t x, xy_t y) {
widget_prepare_text_style(text_edit->widget, GET_CANVAS(text_edit));
point = text_edit_normalize_point(text_edit, x, y);
stb_textedit_click(text_edit, &(impl->state), point.x, point.y);
text_edit_layout(text_edit);
if (impl->single_line || text_edit_is_need_layout(text_edit)) {
text_edit_layout(text_edit);
} else {
text_edit_update_caret_pos(text_edit);
}
return RET_OK;
}
@ -1140,7 +1221,12 @@ ret_t text_edit_drag(text_edit_t* text_edit, xy_t x, xy_t y) {
widget_prepare_text_style(text_edit->widget, GET_CANVAS(text_edit));
point = text_edit_normalize_point(text_edit, x, y);
stb_textedit_drag(text_edit, &(impl->state), point.x, point.y);
text_edit_layout(text_edit);
if (impl->single_line || text_edit_is_need_layout(text_edit)) {
text_edit_layout(text_edit);
} else {
text_edit_update_caret_pos(text_edit);
}
return RET_OK;
}
@ -1221,6 +1307,7 @@ ret_t text_edit_key_down(text_edit_t* text_edit, key_event_t* evt) {
uint32_t key = 0;
wstr_t* text = NULL;
DECL_IMPL(text_edit);
bool_t move_caret_pos = FALSE;
STB_TexteditState* state = NULL;
text_layout_info_t* layout_info = NULL;
return_value_if_fail(impl != NULL, RET_BAD_PARAMS);
@ -1256,26 +1343,34 @@ ret_t text_edit_key_down(text_edit_t* text_edit, key_event_t* evt) {
break;
}
case TK_KEY_LEFT: {
move_caret_pos = TRUE;
key = STB_TEXTEDIT_K_LEFT;
break;
}
case TK_KEY_RIGHT: {
move_caret_pos = TRUE;
key = STB_TEXTEDIT_K_RIGHT;
break;
}
case TK_KEY_DOWN: {
move_caret_pos = TRUE;
key = STB_TEXTEDIT_K_DOWN;
break;
}
case TK_KEY_UP: {
move_caret_pos = TRUE;
key = STB_TEXTEDIT_K_UP;
break;
}
case TK_KEY_HOME: {
move_caret_pos = TRUE;
state->cursor = 0;
key = STB_TEXTEDIT_K_LINESTART;
break;
}
case TK_KEY_END: {
move_caret_pos = TRUE;
state->cursor = text->size;
key = STB_TEXTEDIT_K_LINEEND;
break;
}
@ -1292,37 +1387,44 @@ ret_t text_edit_key_down(text_edit_t* text_edit, key_event_t* evt) {
break;
}
case TK_KEY_PAGEDOWN: {
move_caret_pos = TRUE;
if (impl->single_line) {
key = STB_TEXTEDIT_K_LINEEND;
} else {
int32_t lines = layout_info->h / impl->line_height;
if ((layout_info->virtual_h - layout_info->oy) > layout_info->h) {
key = STB_TEXTEDIT_K_DOWN;
int32_t next_lines = impl->caret_line_index + lines;
int32_t next_y = next_lines * impl->line_height;
if (layout_info->virtual_h > next_y) {
while (lines-- > 0) {
stb_textedit_key(text_edit, state, key);
stb_textedit_key(text_edit, state, STB_TEXTEDIT_K_DOWN);
}
text_edit_layout(text_edit);
} else {
state->cursor = text->size;
stb_textedit_key(text_edit, state, STB_TEXTEDIT_K_LINEEND);
}
goto layout;
return RET_OK;
}
break;
}
case TK_KEY_PAGEUP: {
move_caret_pos = TRUE;
if (impl->single_line) {
key = STB_TEXTEDIT_K_LINESTART;
} else {
int32_t lines = tk_min(layout_info->oy, layout_info->h) / impl->line_height;
int32_t lines = layout_info->h / impl->line_height;
int32_t next_lines = impl->caret_line_index - lines;
if (lines > 0) {
key = STB_TEXTEDIT_K_UP;
if (next_lines > 0) {
while (lines-- > 0) {
stb_textedit_key(text_edit, state, key);
stb_textedit_key(text_edit, state, STB_TEXTEDIT_K_UP);
}
text_edit_layout(text_edit);
} else {
state->cursor = 0;
stb_textedit_key(text_edit, state, STB_TEXTEDIT_K_LINESTART);
}
return RET_OK;
goto layout;
}
break;
}
@ -1371,7 +1473,12 @@ ret_t text_edit_key_down(text_edit_t* text_edit, key_event_t* evt) {
}
stb_textedit_key(text_edit, state, key);
text_edit_layout(text_edit);
layout:
if (!impl->single_line && move_caret_pos && !text_edit_is_need_layout(text_edit)) {
text_edit_update_caret_pos(text_edit);
} else {
text_edit_layout(text_edit);
}
return RET_OK;
}

View File

@ -3581,14 +3581,13 @@ int32_t widget_index_of(widget_t* widget) {
return -1;
}
ret_t widget_prepare_text_style(widget_t* widget, canvas_t* c) {
ret_t widget_prepare_text_style_ex(widget_t* widget, canvas_t* c, color_t default_trans, const char* default_font, uint16_t default_font_size, align_h_t default_align_h, align_v_t default_align_v) {
style_t* style = widget->astyle;
color_t trans = color_init(0, 0, 0, 0);
color_t tc = style_get_color(style, STYLE_ID_TEXT_COLOR, trans);
const char* font_name = style_get_str(style, STYLE_ID_FONT_NAME, NULL);
uint16_t font_size = style_get_int(style, STYLE_ID_FONT_SIZE, TK_DEFAULT_FONT_SIZE);
align_h_t align_h = (align_h_t)style_get_int(style, STYLE_ID_TEXT_ALIGN_H, ALIGN_H_CENTER);
align_v_t align_v = (align_v_t)style_get_int(style, STYLE_ID_TEXT_ALIGN_V, ALIGN_V_MIDDLE);
color_t tc = style_get_color(style, STYLE_ID_TEXT_COLOR, default_trans);
const char* font_name = style_get_str(style, STYLE_ID_FONT_NAME, default_font);
uint16_t font_size = style_get_int(style, STYLE_ID_FONT_SIZE, default_font_size);
align_h_t align_h = (align_h_t)style_get_int(style, STYLE_ID_TEXT_ALIGN_H, default_align_h);
align_v_t align_v = (align_v_t)style_get_int(style, STYLE_ID_TEXT_ALIGN_V, default_align_v);
canvas_set_text_color(c, tc);
canvas_set_font(c, font_name, font_size);
@ -3597,6 +3596,11 @@ ret_t widget_prepare_text_style(widget_t* widget, canvas_t* c) {
return RET_OK;
}
ret_t widget_prepare_text_style(widget_t* widget, canvas_t* c) {
color_t trans = color_init(0, 0, 0, 0);
return widget_prepare_text_style_ex(widget, c, trans, NULL, TK_DEFAULT_FONT_SIZE, ALIGN_H_CENTER, ALIGN_V_MIDDLE);
}
static ret_t widget_copy_style(widget_t* clone, widget_t* widget) {
if (style_is_mutable(widget->astyle) && style_mutable_cast(widget->astyle) != NULL) {
if (!style_is_mutable(clone->astyle)) {

View File

@ -2479,6 +2479,23 @@ ret_t widget_fill_fg_rect(widget_t* widget, canvas_t* c, const rect_t* r,
*/
ret_t widget_prepare_text_style(widget_t* widget, canvas_t* c);
/**
* @method widget_prepare_text_style_ex
* widget的style中取出字体名称canvas中
* 使
*
* @param {widget_t*} widget
* @param {canvas_t*} c
* @param {color_t} default_trans
* @param {const char*} default_font
* @param {uint16_t} default_font_size
* @param {align_h_t} default_align_h
* @param {align_v_t} default_align_v
*
* @return {ret_t} RET_OK表示成功
*/
ret_t widget_prepare_text_style_ex(widget_t* widget, canvas_t* c, color_t default_trans, const char* default_font, uint16_t default_font_size, align_h_t default_align_h, align_v_t default_align_v);
/**
* @method widget_measure_text
*

View File

@ -53,7 +53,7 @@ static ret_t line_number_do_paint_self(widget_t* widget, canvas_t* c) {
if (style_is_valid(widget->astyle)) {
uint32_t line_index = 0;
color_t trans = color_init(0, 0, 0, 0);
widget_prepare_text_style(widget, c);
widget_prepare_text_style_ex(widget, c, trans, NULL, TK_DEFAULT_FONT_SIZE, ALIGN_H_RIGHT, ALIGN_V_TOP);
color_t active_bg =
style_get_color(widget->astyle, LINE_NUMBER_STYLE_ACTIVE_LINE_BG_COLOR, trans);
color_t highlight_bg =

View File

@ -244,6 +244,7 @@ static ret_t mledit_get_prop(widget_t* widget, const char* name, value_t* v) {
if (margin == 0) {
margin = mledit->top_margin != 0 ? mledit->top_margin : mledit->margin;
}
value_set_int(v, margin);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_BOTTOM_MARGIN)) {
uint32_t margin = 0;
@ -253,6 +254,7 @@ static ret_t mledit_get_prop(widget_t* widget, const char* name, value_t* v) {
if (margin == 0) {
margin = mledit->bottom_margin != 0 ? mledit->bottom_margin : mledit->margin;
}
value_set_int(v, margin);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_TIPS)) {
value_set_str(v, mledit->tips);