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
+98 -66
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_event(const lv_obj_class_t * class_p, 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 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 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 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,
@@ -72,6 +72,8 @@ const lv_obj_class_t lv_spangroup_class = {
.destructor_cb = lv_spangroup_destructor,
.event_cb = lv_spangroup_event,
.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);
span->txt = (char *)"";
span->static_flag = 1;
span->spangroup = obj;
refresh_self_size(obj);
lv_obj_invalidate(obj);
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)
{
if(obj == NULL) {
if(obj == NULL || span == NULL) {
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;
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->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)
{
lv_spangroup_t * spans = (lv_spangroup_t *)obj;
if(spans->align == align) return;
spans->align = align;
lv_obj_invalidate(obj);
lv_obj_set_style_text_align(obj, align, LV_PART_MAIN);
}
/**
@@ -228,7 +232,8 @@ void lv_spangroup_set_indent(lv_obj_t * obj, lv_coord_t indent)
if(spans->indent == indent) return;
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_spangroup_t * spans = (lv_spangroup_t *)obj;
return spans->align;
return lv_obj_get_style_text_align(obj, LV_PART_MAIN);
}
/**
@@ -301,24 +305,33 @@ void lv_spangroup_refr_mode(lv_obj_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) {
lv_coord_t width = lv_spangroup_get_expand_width(obj);
lv_coord_t height = lv_spangroup_get_max_line_h(obj);
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);
lv_obj_set_width(obj, LV_SIZE_CONTENT);
lv_obj_set_height(obj, LV_SIZE_CONTENT);
}
else if(spans->mode == LV_SPAN_MODE_BREAK) {
lv_coord_t height = lv_spangroup_get_expand_height(obj, lv_obj_get_width(obj));
lv_obj_set_height(obj, height);
if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT) {
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.
*/
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;
}
/**
* 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.
*/
lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width)
{
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;
}
/* init draw variable */
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 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);
lv_coord_t max_width = width - left_pad - right_pad;
lv_coord_t max_width = width;
lv_coord_t max_w = max_width - spans->indent; /* first line need minus indent */
/* 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;
}
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;
}
@@ -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_ll_init(&spans->child_ll, sizeof(lv_span_t));
spans->indent = 0;
spans->align = LV_TEXT_ALIGN_LEFT;
spans->mode = LV_SPAN_MODE_FIXED;
spans->mode = LV_SPAN_MODE_EXPAND;
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)
@@ -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_obj_t * obj = lv_event_get_target(e);
lv_spangroup_t * spans = (lv_spangroup_t *)obj;
if(code == LV_EVENT_DRAW_MAIN) {
draw_main(e);
}
else if(code == LV_EVENT_STYLE_CHANGED) {
lv_spangroup_refr_mode(obj);
refresh_self_size(obj);
}
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);
lv_area_t txt_coords;
get_txt_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_obj_get_content_coords(obj, &txt_coords);
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.
*/
@@ -730,7 +753,7 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area
uint32_t cur_txt_ofs = 0;
lv_snippet_t snippet; /* use to save cur_span info and push it to stack */
memset(&snippet, 0, sizeof(snippet));
/* the loop control how many lines need to draw */
while(cur_span) {
lv_coord_t max_line_h = 0; /* the max height of span-font when a line have a lot of span */
@@ -825,17 +848,18 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area
}
/* 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 txts_w = 0;
for(int i = 0; i < item_cnt; i++) {
lv_snippet_t * pinfo = lv_get_snippet(i);
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;
}
else if(spans->align == LV_TEXT_ALIGN_RIGHT) {
else if(align == LV_TEXT_ALIGN_RIGHT) {
align_ofs = max_width - txts_w;
}
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
+10 -7
View File
@@ -41,19 +41,22 @@ enum {
typedef uint8_t lv_span_mode_t;
typedef struct {
char * txt;
lv_style_t style;
uint8_t static_flag : 1;
char * txt; /* a pointer to display text */
lv_obj_t * spangroup; /* a pointer to spangroup */
lv_style_t style; /* display text style */
uint8_t static_flag : 1;/* the text is static flag */
} lv_span_t;
/** Data of label*/
typedef struct {
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;
uint8_t mode : 2;
uint8_t align : 2;
uint8_t overflow : 1;
uint8_t mode : 2; /* details see lv_span_mode_t */
uint8_t overflow : 1; /* details see lv_span_overflow_t */
uint8_t refresh : 1; /* the spangroup need refresh cache_w and cache_h */
} lv_spangroup_t;
extern const lv_obj_class_t lv_spangroup_class;