rework label

This commit is contained in:
lixianjing 2021-04-28 15:20:32 +08:00
parent 9759614b44
commit 050e03e51f
5 changed files with 131 additions and 131 deletions

View File

@ -1,5 +1,8 @@
# 最新动态
2021/04/28
* 重构 label 并完善对 margin 的支持。
2021/04/27
* 完善 label 对 auto adjust size 的处理。
* 完善 line\_parser\_next让空格在行尾。

View File

@ -4569,3 +4569,24 @@ bool_t widget_get_feedback(widget_t* widget) {
return widget->feedback;
}
rect_t widget_get_content_area(widget_t* widget) {
if (widget != NULL && widget->astyle != NULL) {
style_t* style = widget->astyle;
int32_t margin = style_get_int(style, STYLE_ID_MARGIN, 2);
int32_t margin_top = style_get_int(style, STYLE_ID_MARGIN_TOP, margin);
int32_t margin_left = style_get_int(style, STYLE_ID_MARGIN_LEFT, margin);
int32_t margin_right = style_get_int(style, STYLE_ID_MARGIN_RIGHT, margin);
int32_t margin_bottom = style_get_int(style, STYLE_ID_MARGIN_BOTTOM, margin);
int32_t w = widget->w - margin_left - margin_right;
int32_t h = widget->h - margin_top - margin_bottom;
return rect_init(margin_left, margin_top, w, h);
} else {
if (widget != NULL) {
return rect_init(0, 0, widget->w, widget->h);
} else {
return rect_init(0, 0, 0, 0);
}
}
}

View File

@ -2845,6 +2845,15 @@ ret_t widget_end_wait_pointer_cursor(widget_t* widget);
*/
ret_t widget_set_style(widget_t* widget, const char* state_and_name, const value_t* value);
/**
* @method widget_get_content_area
* widget去掉margin之外的区域
* @param {widget_t*} widget
*
* @return {rect_t} margin之外的区域
*/
rect_t widget_get_content_area(widget_t* widget);
/**
* @method widget_calc_icon_text_rect
* icon text的位置

View File

@ -28,49 +28,39 @@
static ret_t label_auto_adjust_size(widget_t* widget);
static ret_t label_paint_text_mlines(widget_t* widget, canvas_t* c, line_parser_t* p) {
int32_t x = 0;
int32_t y = 0;
int32_t w = 0;
int32_t h_text = 0;
static ret_t label_paint_text_mlines(widget_t* widget, canvas_t* c, line_parser_t* p, int32_t x,
int32_t y, int32_t w, int32_t h) {
int32_t top = y;
int32_t bottom = y + h;
style_t* style = widget->astyle;
int32_t font_size = c->font_size;
int32_t margin = style_get_int(style, STYLE_ID_MARGIN, 2);
int32_t spacer = style_get_int(style, STYLE_ID_SPACER, 2);
int32_t line_height = font_size + style_get_int(style, STYLE_ID_SPACER, 2);
align_v_t align_v = (align_v_t)style_get_int(style, STYLE_ID_TEXT_ALIGN_V, ALIGN_V_MIDDLE);
align_h_t align_h = (align_h_t)style_get_int(style, STYLE_ID_TEXT_ALIGN_H, ALIGN_H_CENTER);
int32_t line_height = font_size + spacer;
x = margin;
y = margin;
w = widget->w - margin - margin;
h_text = p->total_lines * line_height;
int32_t h_text = p->total_lines * line_height;
switch (align_v) {
case ALIGN_V_TOP: {
y = margin;
break;
}
case ALIGN_V_BOTTOM: {
y = widget->h - margin - h_text;
break;
}
default: {
case ALIGN_V_MIDDLE: {
y = (widget->h - h_text) / 2;
break;
}
case ALIGN_V_BOTTOM: {
y = y + h - h_text;
break;
}
default: {
break;
}
}
if (y < margin) {
y = margin;
}
y = tk_max(y, top);
canvas_set_text_align(c, align_h, align_v);
while (line_parser_next(p) == RET_OK) {
uint32_t size = 0;
rect_t r = rect_init(x, y, w, font_size);
if ((y + font_size) > widget->h) {
if ((y + font_size) > bottom) {
break;
}
@ -79,6 +69,7 @@ static ret_t label_paint_text_mlines(widget_t* widget, canvas_t* c, line_parser_
break;
}
}
canvas_draw_text_in_rect(c, p->line, size, &r);
y += line_height;
@ -90,16 +81,15 @@ static ret_t label_paint_text_mlines(widget_t* widget, canvas_t* c, line_parser_
static ret_t label_paint_text(widget_t* widget, canvas_t* c, const wchar_t* str, uint32_t size) {
line_parser_t p;
label_t* label = LABEL(widget);
style_t* style = widget->astyle;
int32_t margin = style_get_int(style, STYLE_ID_MARGIN, 2);
int32_t w = widget->w - margin - margin;
rect_t r = widget_get_content_area(widget);
return_value_if_fail(line_parser_init(&p, c, widget->text.str, widget->text.size, c->font_size, w,
label->line_wrap, label->word_wrap) == RET_OK,
return_value_if_fail((r.w > 0 && r.h > c->font_size), RET_FAIL);
return_value_if_fail(line_parser_init(&p, c, widget->text.str, widget->text.size, c->font_size,
r.w, label->line_wrap, label->word_wrap) == RET_OK,
RET_BAD_PARAMS);
if (p.total_lines > 1) {
return label_paint_text_mlines(widget, c, &p);
return label_paint_text_mlines(widget, c, &p, r.x, r.y, r.w, r.h);
} else {
wstr_t str = widget->text;
str.size = size;
@ -152,51 +142,6 @@ static wh_t label_get_text_line_max_w(widget_t* widget, canvas_t* c) {
return line_max_w;
}
ret_t label_resize_to_content(widget_t* widget, uint32_t min_w, uint32_t max_w, uint32_t min_h,
uint32_t max_h) {
wh_t w = 0;
wh_t h = 0;
wh_t tmp_w = 0;
int32_t margin = 0;
int32_t spacer = 0;
int32_t line_height = 0;
style_t* style = NULL;
line_parser_t p;
label_t* label = LABEL(widget);
canvas_t* c = widget_get_canvas(widget);
return_value_if_fail(label != NULL, RET_BAD_PARAMS);
style = widget->astyle;
margin = style_get_int(style, STYLE_ID_MARGIN, 2);
spacer = style_get_int(style, STYLE_ID_SPACER, 2);
widget_prepare_text_style(widget, c);
line_height = c->font_size + spacer;
w = label_get_text_line_max_w(widget, c);
w = tk_clampi(w, min_w, max_w);
if (w >= max_w) {
tmp_w = max_w - 2 * margin;
} else {
tmp_w = w;
w = w + 2 * margin;
if (w >= max_w) {
w = max_w;
tmp_w = max_w - 2 * margin;
}
}
return_value_if_fail(line_parser_init(&p, c, widget->text.str, widget->text.size, c->font_size,
tmp_w, label->line_wrap, label->word_wrap) == RET_OK,
RET_BAD_PARAMS);
h = p.total_lines * line_height + 2 * margin;
h = tk_clampi(h, min_h, max_h);
widget_resize(widget, w, h);
return RET_OK;
}
ret_t label_set_length(widget_t* widget, int32_t length) {
label_t* label = LABEL(widget);
return_value_if_fail(label != NULL, RET_BAD_PARAMS);
@ -277,32 +222,72 @@ static ret_t label_set_prop(widget_t* widget, const char* name, const value_t* v
return RET_NOT_FOUND;
}
static ret_t label_auto_adjust_size(widget_t* widget) {
static ret_t label_auto_adjust_size_impl(widget_t* widget, canvas_t* c, uint32_t min_w,
uint32_t max_w, uint32_t min_h, uint32_t max_h) {
wh_t w = 0;
wh_t max_line_w = 0;
int32_t max_w = 0;
int32_t margin = 0;
int32_t spacer = 0;
int32_t line_height = 0;
style_t* style = NULL;
line_parser_t p;
wh_t max_line_w = 0;
int32_t line_height = 0;
label_t* label = LABEL(widget);
canvas_t* c = widget_get_canvas(widget);
return_value_if_fail(label != NULL, RET_BAD_PARAMS);
return_value_if_fail(c != NULL && widget->astyle != NULL, RET_BAD_PARAMS);
style_t* style = widget->astyle;
int32_t margin = style_get_int(style, STYLE_ID_MARGIN, 2);
int32_t margin_top = style_get_int(style, STYLE_ID_MARGIN_TOP, margin);
int32_t margin_left = style_get_int(style, STYLE_ID_MARGIN_LEFT, margin);
int32_t margin_right = style_get_int(style, STYLE_ID_MARGIN_RIGHT, margin);
int32_t margin_bottom = style_get_int(style, STYLE_ID_MARGIN_BOTTOM, margin);
int32_t spacer = style_get_int(style, STYLE_ID_SPACER, 2);
if (!widget_is_window_created(widget)) {
widget_prepare_text_style(widget, c);
line_height = c->font_size + spacer;
if (widget->text.size == 0) {
widget->h = line_height;
return RET_OK;
}
style = widget->astyle;
margin = style_get_int(style, STYLE_ID_MARGIN, 2);
spacer = style_get_int(style, STYLE_ID_SPACER, 2);
widget_prepare_text_style(widget, c);
line_height = c->font_size + spacer;
max_line_w = label_get_text_line_max_w(widget, c);
if (label->line_wrap) {
w = widget->w - margin_left - margin_right;
if (max_w != 0) {
w = max_line_w;
}
} else {
w = max_line_w;
}
if (widget->text.size == 0) {
widget->h = line_height;
if (max_w != 0) {
if (w > max_w) {
w = max_w - margin_left - margin_right;
}
}
return_value_if_fail(w > 0, RET_BAD_PARAMS);
return_value_if_fail(line_parser_init(&p, c, widget->text.str, widget->text.size, c->font_size, w,
label->line_wrap, label->word_wrap) == RET_OK,
RET_BAD_PARAMS);
widget->w = w + margin_left + margin_right;
widget->h = line_height * p.total_lines + margin_top + margin_bottom;
widget->w = tk_max(widget->w, min_w);
widget->h = tk_max(widget->h, min_h);
if (max_w > 0) {
widget->w = tk_min(widget->w, max_w);
}
if (max_h > 0) {
widget->h = tk_min(widget->h, max_h);
}
return RET_OK;
}
static ret_t label_auto_adjust_size(widget_t* widget) {
int32_t max_w = 0;
label_t* label = LABEL(widget);
canvas_t* c = widget_get_canvas(widget);
return_value_if_fail(c != NULL, RET_BAD_PARAMS);
return_value_if_fail(label != NULL && widget->astyle != NULL, RET_BAD_PARAMS);
if (!widget->auto_adjust_size || !widget_is_window_created(widget)) {
return RET_OK;
}
@ -310,31 +295,16 @@ static ret_t label_auto_adjust_size(widget_t* widget) {
max_w = label->max_w > 0 ? label->max_w : (widget->parent->w + label->max_w);
}
max_line_w = label_get_text_line_max_w(widget, c);
if (label->line_wrap) {
w = widget->w;
if (max_w != 0) {
w = max_line_w + 2 * margin;
}
} else {
w = max_line_w + 2 * margin;
}
return label_auto_adjust_size_impl(widget, c, 0, max_w, 0, 0xffff);
}
if (max_w != 0) {
if (w > max_w) {
w = max_w;
}
}
ret_t label_resize_to_content(widget_t* widget, uint32_t min_w, uint32_t max_w, uint32_t min_h,
uint32_t max_h) {
label_t* label = LABEL(widget);
canvas_t* c = widget_get_canvas(widget);
return_value_if_fail(label != NULL && c != NULL && widget->astyle != NULL, RET_BAD_PARAMS);
return_value_if_fail(
line_parser_init(&p, c, widget->text.str, widget->text.size, c->font_size, w - 2 * margin,
label->line_wrap, label->word_wrap) == RET_OK,
RET_BAD_PARAMS);
widget->w = w;
widget->h = line_height * p.total_lines + 2 * margin;
return RET_OK;
return label_auto_adjust_size_impl(widget, c, min_w, max_w, min_h, max_h);
}
static ret_t label_on_event(widget_t* widget, event_t* e) {
@ -345,18 +315,13 @@ static ret_t label_on_event(widget_t* widget, event_t* e) {
switch (type) {
case EVT_RESIZE:
case EVT_MOVE_RESIZE: {
if (widget->auto_adjust_size) {
label_auto_adjust_size(widget);
break;
}
break;
}
case EVT_WINDOW_WILL_OPEN: {
if (widget->auto_adjust_size) {
label_auto_adjust_size(widget);
break;
}
}
default:
break;
}
@ -365,7 +330,7 @@ static ret_t label_on_event(widget_t* widget, event_t* e) {
}
static const char* const s_label_properties[] = {WIDGET_PROP_LENGTH, WIDGET_PROP_LINE_WRAP,
WIDGET_PROP_WORD_WRAP, NULL};
WIDGET_PROP_MAX_W, WIDGET_PROP_WORD_WRAP, NULL};
TK_DECL_VTABLE(label) = {.size = sizeof(label_t),
.type = WIDGET_TYPE_LABEL,
@ -383,6 +348,7 @@ widget_t* label_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
label_t* label = LABEL(widget);
return_value_if_fail(label != NULL, NULL);
label->max_w = 0;
label->length = -1;
label->line_wrap = FALSE;
label->word_wrap = FALSE;

View File

@ -87,14 +87,15 @@ typedef struct _label_t {
/**
* @property {bool_t} line_wrap
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
*
* (FALSE)
*/
bool_t line_wrap;
/**
* @property {bool_t} word_wrap
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* ()
* (FALSE)
* >
*/
bool_t word_wrap;
@ -123,7 +124,7 @@ widget_t* label_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method label_set_length
* (0)
* (0)
* @annotation ["scriptable"]
* @param {widget_t*} widget
* @param {int32_t} length