fix (span) fill LV_EVENT_GET_SELF_SIZE (#2360)

Co-authored-by: guowei15 <guowei15@xiaomi.com>
This commit is contained in:
guoweilkd
2021-07-08 22:40:43 +08:00
committed by GitHub
parent 27d88de899
commit 2a6bfe8cf9
2 changed files with 108 additions and 73 deletions
+97 -65
View File
@@ -40,6 +40,7 @@ static void lv_spangroup_destructor(const lv_obj_class_t * class_p, lv_obj_t * o
static void lv_spangroup_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_spangroup_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
static void lv_spangroup_event(const lv_obj_class_t * class_p, lv_event_t * e); static void lv_spangroup_event(const lv_obj_class_t * class_p, lv_event_t * e);
static void draw_main(lv_event_t * e); static void draw_main(lv_event_t * e);
static void refresh_self_size(lv_obj_t * obj);
static const lv_font_t * lv_span_get_style_text_font(lv_obj_t * par, lv_span_t * span); static const lv_font_t * lv_span_get_style_text_font(lv_obj_t * par, lv_span_t * span);
static lv_coord_t lv_span_get_style_text_letter_space(lv_obj_t * par, lv_span_t * span); static lv_coord_t lv_span_get_style_text_letter_space(lv_obj_t * par, lv_span_t * span);
@@ -50,7 +51,6 @@ static lv_opa_t lv_span_get_style_text_blend_mode(lv_obj_t * par, lv_span_t * sp
static int32_t lv_span_get_style_text_decor(lv_obj_t * par, lv_span_t * span); static int32_t lv_span_get_style_text_decor(lv_obj_t * par, lv_span_t * span);
static inline void span_text_check(const char ** text); static inline void span_text_check(const char ** text);
static void get_txt_coords(const lv_obj_t * span, lv_area_t * area);
static void lv_draw_span(lv_obj_t * spans, const lv_area_t * coords, const lv_area_t * mask); static void lv_draw_span(lv_obj_t * spans, const lv_area_t * coords, const lv_area_t * mask);
static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, lv_coord_t letter_space, static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, lv_coord_t letter_space,
lv_coord_t max_width, lv_text_flag_t flag, lv_coord_t * use_width, lv_coord_t max_width, lv_text_flag_t flag, lv_coord_t * use_width,
@@ -72,6 +72,8 @@ const lv_obj_class_t lv_spangroup_class = {
.destructor_cb = lv_spangroup_destructor, .destructor_cb = lv_spangroup_destructor,
.event_cb = lv_spangroup_event, .event_cb = lv_spangroup_event,
.instance_size = sizeof(lv_spangroup_t), .instance_size = sizeof(lv_spangroup_t),
.width_def = LV_SIZE_CONTENT,
.height_def = LV_SIZE_CONTENT,
}; };
/********************** /**********************
@@ -112,8 +114,10 @@ lv_span_t * lv_spangroup_new_span(lv_obj_t * obj)
lv_style_init(&span->style); lv_style_init(&span->style);
span->txt = (char *)""; span->txt = (char *)"";
span->static_flag = 1; span->static_flag = 1;
span->spangroup = obj;
refresh_self_size(obj);
lv_obj_invalidate(obj);
return span; return span;
} }
@@ -124,7 +128,7 @@ lv_span_t * lv_spangroup_new_span(lv_obj_t * obj)
*/ */
void lv_spangroup_del_span(lv_obj_t * obj, lv_span_t * span) void lv_spangroup_del_span(lv_obj_t * obj, lv_span_t * span)
{ {
if(obj == NULL) { if(obj == NULL || span == NULL) {
return; return;
} }
@@ -142,7 +146,7 @@ void lv_spangroup_del_span(lv_obj_t * obj, lv_span_t * span)
} }
} }
lv_spangroup_refr_mode(obj); refresh_self_size(obj);
} }
/*===================== /*=====================
@@ -168,6 +172,8 @@ void lv_span_set_text(lv_span_t * span, const char * text)
} }
span->static_flag = 0; span->static_flag = 0;
strcpy(span->txt, text); strcpy(span->txt, text);
refresh_self_size(span->spangroup);
} }
/** /**
@@ -187,6 +193,8 @@ void lv_span_set_text_static(lv_span_t * span, const char * text)
} }
span->static_flag = 1; span->static_flag = 1;
span->txt = (char *)text; span->txt = (char *)text;
refresh_self_size(span->spangroup);
} }
/** /**
@@ -196,11 +204,7 @@ void lv_span_set_text_static(lv_span_t * span, const char * text)
*/ */
void lv_spangroup_set_align(lv_obj_t * obj, lv_text_align_t align) void lv_spangroup_set_align(lv_obj_t * obj, lv_text_align_t align)
{ {
lv_spangroup_t * spans = (lv_spangroup_t *)obj; lv_obj_set_style_text_align(obj, align, LV_PART_MAIN);
if(spans->align == align) return;
spans->align = align;
lv_obj_invalidate(obj);
} }
/** /**
@@ -228,7 +232,8 @@ void lv_spangroup_set_indent(lv_obj_t * obj, lv_coord_t indent)
if(spans->indent == indent) return; if(spans->indent == indent) return;
spans->indent = indent; spans->indent = indent;
lv_obj_invalidate(obj);
refresh_self_size(obj);
} }
/** /**
@@ -256,8 +261,7 @@ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode)
*/ */
lv_text_align_t lv_spangroup_get_align(lv_obj_t * obj) lv_text_align_t lv_spangroup_get_align(lv_obj_t * obj)
{ {
lv_spangroup_t * spans = (lv_spangroup_t *)obj; return lv_obj_get_style_text_align(obj, LV_PART_MAIN);
return spans->align;
} }
/** /**
@@ -301,24 +305,33 @@ void lv_spangroup_refr_mode(lv_obj_t * obj)
{ {
lv_spangroup_t * spans = (lv_spangroup_t *)obj; lv_spangroup_t * spans = (lv_spangroup_t *)obj;
if(_lv_ll_get_head(&spans->child_ll) == NULL) {
return;
}
if(spans->mode == LV_SPAN_MODE_EXPAND) { if(spans->mode == LV_SPAN_MODE_EXPAND) {
lv_coord_t width = lv_spangroup_get_expand_width(obj); lv_obj_set_width(obj, LV_SIZE_CONTENT);
lv_coord_t height = lv_spangroup_get_max_line_h(obj); lv_obj_set_height(obj, LV_SIZE_CONTENT);
lv_coord_t top_pad = lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
lv_coord_t bottom_pad = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
lv_obj_set_width(obj, width + spans->indent);
lv_obj_set_height(obj, height + top_pad + bottom_pad);
} }
else if(spans->mode == LV_SPAN_MODE_BREAK) { else if(spans->mode == LV_SPAN_MODE_BREAK) {
lv_coord_t height = lv_spangroup_get_expand_height(obj, lv_obj_get_width(obj)); if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT) {
lv_obj_set_height(obj, height); lv_obj_set_width(obj, 100);
}
lv_obj_set_height(obj, LV_SIZE_CONTENT);
}
else if(spans->mode == LV_SPAN_MODE_FIXED) {
/* use this mode, The user needs to set the size. */
/* This is just to prevent an infinite loop. */
if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT) {
lv_obj_set_width(obj, 100);
}
if(lv_obj_get_style_height(obj, LV_PART_MAIN) == LV_SIZE_CONTENT) {
lv_coord_t width = lv_obj_get_style_width(obj, LV_PART_MAIN);
if(LV_COORD_IS_PCT(width)) {
width = 100;
}
lv_coord_t height = lv_spangroup_get_expand_height(obj, width);
lv_obj_set_content_height(obj, height);
}
} }
lv_obj_invalidate(obj); refresh_self_size(obj);
} }
/** /**
@@ -343,7 +356,7 @@ lv_coord_t lv_spangroup_get_max_line_h(lv_obj_t * obj)
} }
/** /**
* get the width when all span of spangroup on a line. include spangroup pad. * get the width when all span of spangroup on a line. not included spangroup pad, border width.
* @param obj pointer to a spangroup object. * @param obj pointer to a spangroup object.
*/ */
lv_coord_t lv_spangroup_get_expand_width(lv_obj_t * obj) lv_coord_t lv_spangroup_get_expand_width(lv_obj_t * obj)
@@ -370,30 +383,24 @@ lv_coord_t lv_spangroup_get_expand_width(lv_obj_t * obj)
} }
} }
lv_coord_t left_pad = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
lv_coord_t right_pad = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
width = width + left_pad + right_pad;
return width; return width;
} }
/** /**
* get the height with width fixed. the height include spangroup pad. * get the height with width fixed. Height and width are not included spangroup pad, border width.
* @param obj pointer to a spangroup object. * @param obj pointer to a spangroup object.
*/ */
lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width)
{ {
lv_spangroup_t * spans = (lv_spangroup_t *)obj; lv_spangroup_t * spans = (lv_spangroup_t *)obj;
if(_lv_ll_get_head(&spans->child_ll) == NULL) { if(_lv_ll_get_head(&spans->child_ll) == NULL || width <= 0) {
return 0; return 0;
} }
/* init draw variable */ /* init draw variable */
lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE; lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE;
lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN);
lv_coord_t left_pad = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); lv_coord_t max_width = width;
lv_coord_t right_pad = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
lv_coord_t max_width = width - left_pad - right_pad;
lv_coord_t max_w = max_width - spans->indent; /* first line need minus indent */ lv_coord_t max_w = max_width - spans->indent; /* first line need minus indent */
/* coords of draw span-txt */ /* coords of draw span-txt */
@@ -469,10 +476,6 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width)
max_w = max_width; max_w = max_width;
} }
lv_coord_t top_pad = lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
lv_coord_t bottom_pad = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
txt_pos.y = txt_pos.y + top_pad + bottom_pad - line_space;
return txt_pos.y; return txt_pos.y;
} }
@@ -486,9 +489,11 @@ static void lv_spangroup_constructor(const lv_obj_class_t * class_p, lv_obj_t *
lv_spangroup_t * spans = (lv_spangroup_t *)obj; lv_spangroup_t * spans = (lv_spangroup_t *)obj;
_lv_ll_init(&spans->child_ll, sizeof(lv_span_t)); _lv_ll_init(&spans->child_ll, sizeof(lv_span_t));
spans->indent = 0; spans->indent = 0;
spans->align = LV_TEXT_ALIGN_LEFT; spans->mode = LV_SPAN_MODE_EXPAND;
spans->mode = LV_SPAN_MODE_FIXED;
spans->overflow = LV_SPAN_OVERFLOW_CLIP; spans->overflow = LV_SPAN_OVERFLOW_CLIP;
spans->cache_w = 0;
spans->cache_h = 0;
spans->refresh = 1;
} }
static void lv_spangroup_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) static void lv_spangroup_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
@@ -516,15 +521,51 @@ static void lv_spangroup_event(const lv_obj_class_t * class_p, lv_event_t * e)
lv_event_code_t code = lv_event_get_code(e); lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e); lv_obj_t * obj = lv_event_get_target(e);
lv_spangroup_t * spans = (lv_spangroup_t *)obj;
if(code == LV_EVENT_DRAW_MAIN) { if(code == LV_EVENT_DRAW_MAIN) {
draw_main(e); draw_main(e);
} }
else if(code == LV_EVENT_STYLE_CHANGED) { else if(code == LV_EVENT_STYLE_CHANGED) {
lv_spangroup_refr_mode(obj); refresh_self_size(obj);
} }
else if(code == LV_EVENT_SIZE_CHANGED) { else if(code == LV_EVENT_SIZE_CHANGED) {
lv_spangroup_refr_mode(obj); refresh_self_size(obj);
}
else if(code == LV_EVENT_GET_SELF_SIZE) {
lv_coord_t width = 0;
lv_coord_t height = 0;
lv_point_t * self_size = lv_event_get_param(e);
if(spans->mode == LV_SPAN_MODE_EXPAND) {
if(spans->refresh) {
spans->cache_w = lv_spangroup_get_expand_width(obj);
spans->cache_h = lv_spangroup_get_max_line_h(obj);
spans->refresh = 0;
}
width = spans->cache_w;
height = spans->cache_h;
}
else if(spans->mode == LV_SPAN_MODE_BREAK) {
width = lv_obj_get_content_width(obj);
if(self_size->y >= 0) {
if(width != spans->cache_w || spans->refresh) {
height = lv_spangroup_get_expand_height(obj, width);
spans->cache_w = width;
spans->cache_h = height;
spans->refresh = 0;
}
else {
height = spans->cache_h;
}
}
}
else if(spans->mode == LV_SPAN_MODE_FIXED) {
width = self_size->x >= 0 ? lv_obj_get_content_width(obj) : 0;
height = self_size->y >= 0 ? lv_obj_get_content_height(obj) : 0;
}
self_size->x = LV_MAX(self_size->x, width);
self_size->y = LV_MAX(self_size->y, height);
} }
} }
@@ -534,29 +575,11 @@ static void draw_main(lv_event_t * e)
const lv_area_t * clip_area = lv_event_get_param(e); const lv_area_t * clip_area = lv_event_get_param(e);
lv_area_t txt_coords; lv_area_t txt_coords;
get_txt_coords(obj, &txt_coords); lv_obj_get_content_coords(obj, &txt_coords);
lv_area_t txt_clip;
bool is_common = _lv_area_intersect(&txt_clip, clip_area, &txt_coords);
if(!is_common) return;
lv_draw_span(obj, &txt_coords, clip_area); lv_draw_span(obj, &txt_coords, clip_area);
} }
static void get_txt_coords(const lv_obj_t * obj, lv_area_t * area)
{
lv_obj_get_coords(obj, area);
lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
area->x1 += left;
area->x2 -= right;
area->y1 += top;
area->y2 -= bottom;
}
/** /**
* @return true for txt fill the max_width. * @return true for txt fill the max_width.
*/ */
@@ -825,17 +848,18 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area
} }
/* align deal with */ /* align deal with */
if(spans->align != LV_TEXT_ALIGN_LEFT) { lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN);
if(align != LV_TEXT_ALIGN_LEFT) {
lv_coord_t align_ofs = 0; lv_coord_t align_ofs = 0;
lv_coord_t txts_w = 0; lv_coord_t txts_w = 0;
for(int i = 0; i < item_cnt; i++) { for(int i = 0; i < item_cnt; i++) {
lv_snippet_t * pinfo = lv_get_snippet(i); lv_snippet_t * pinfo = lv_get_snippet(i);
txts_w += pinfo->txt_w; txts_w += pinfo->txt_w;
} }
if(spans->align == LV_TEXT_ALIGN_CENTER) { if(align == LV_TEXT_ALIGN_CENTER) {
align_ofs = (max_width - txts_w) / 2; align_ofs = (max_width - txts_w) / 2;
} }
else if(spans->align == LV_TEXT_ALIGN_RIGHT) { else if(align == LV_TEXT_ALIGN_RIGHT) {
align_ofs = max_width - txts_w; align_ofs = max_width - txts_w;
} }
txt_pos.x += align_ofs; txt_pos.x += align_ofs;
@@ -950,4 +974,12 @@ Next_line_init:
} }
} }
static void refresh_self_size(lv_obj_t * obj)
{
lv_spangroup_t * spans = (lv_spangroup_t *)obj;
spans->refresh = 1;
lv_obj_refresh_self_size(obj);
lv_obj_invalidate(obj);
}
#endif #endif
+10 -7
View File
@@ -41,19 +41,22 @@ enum {
typedef uint8_t lv_span_mode_t; typedef uint8_t lv_span_mode_t;
typedef struct { typedef struct {
char * txt; char * txt; /* a pointer to display text */
lv_style_t style; lv_obj_t * spangroup; /* a pointer to spangroup */
uint8_t static_flag : 1; lv_style_t style; /* display text style */
uint8_t static_flag : 1;/* the text is static flag */
} lv_span_t; } lv_span_t;
/** Data of label*/ /** Data of label*/
typedef struct { typedef struct {
lv_obj_t obj; lv_obj_t obj;
lv_coord_t indent; lv_coord_t indent; /* first line indent */
lv_coord_t cache_w; /* the cache automatically calculates the width */
lv_coord_t cache_h; /* similar cache_w */
lv_ll_t child_ll; lv_ll_t child_ll;
uint8_t mode : 2; uint8_t mode : 2; /* details see lv_span_mode_t */
uint8_t align : 2; uint8_t overflow : 1; /* details see lv_span_overflow_t */
uint8_t overflow : 1; uint8_t refresh : 1; /* the spangroup need refresh cache_w and cache_h */
} lv_spangroup_t; } lv_spangroup_t;
extern const lv_obj_class_t lv_spangroup_class; extern const lv_obj_class_t lv_spangroup_class;