mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-24 08:16:29 +08:00
fix (span) fill LV_EVENT_GET_SELF_SIZE (#2360)
Co-authored-by: guowei15 <guowei15@xiaomi.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user