mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-30 13:14:37 +08:00
feat(span): add an interface for setting the number of lines (#3200)
* fix draw: remove the high overflow judgment code
This commit is contained in:
parent
9a0a74813d
commit
47791926f9
@ -58,6 +58,9 @@ Use `lv_spangroup_set_overflow(spangroup, LV_SPAN_OVERFLOW_CLIP)` to set object
|
||||
### first line indent
|
||||
Use `lv_spangroup_set_indent(spangroup, 20)` to set the indent of the first line. all modes support pixel units, in addition to LV_SPAN_MODE_FIXED and LV_SPAN_MODE_BREAK mode supports percentage units too.
|
||||
|
||||
### lines
|
||||
Use `lv_spangroup_set_lines(spangroup, 10)` to set the maximum number of lines to be displayed in LV_SPAN_MODE_BREAK mode, negative values indicate no limit.
|
||||
|
||||
## Events
|
||||
No special events are sent by this widget.
|
||||
|
||||
|
@ -209,6 +209,14 @@ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode)
|
||||
lv_spangroup_refr_mode(obj);
|
||||
}
|
||||
|
||||
void lv_spangroup_set_lines(lv_obj_t * obj, int32_t lines)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_spangroup_t * spans = (lv_spangroup_t *)obj;
|
||||
spans->lines = lines;
|
||||
lv_spangroup_refr_mode(obj);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@ -289,6 +297,13 @@ lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj)
|
||||
return spans->mode;
|
||||
}
|
||||
|
||||
int32_t lv_spangroup_get_lines(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_spangroup_t * spans = (lv_spangroup_t *)obj;
|
||||
return spans->lines;
|
||||
}
|
||||
|
||||
void lv_spangroup_refr_mode(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
@ -400,6 +415,8 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width)
|
||||
lv_snippet_t snippet; /* use to save cur_span info and push it to stack */
|
||||
memset(&snippet, 0, sizeof(snippet));
|
||||
|
||||
int32_t line_cnt = 0;
|
||||
int32_t lines = spans->lines < 0 ? INT32_MAX : spans->lines;
|
||||
/* the loop control how many lines need to draw */
|
||||
while(cur_span) {
|
||||
int snippet_cnt = 0;
|
||||
@ -467,6 +484,10 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width)
|
||||
txt_pos.x = 0;
|
||||
txt_pos.y += max_line_h;
|
||||
max_w = max_width;
|
||||
line_cnt += 1;
|
||||
if(line_cnt >= lines) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
txt_pos.y -= line_space;
|
||||
|
||||
@ -483,6 +504,7 @@ 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->lines = -1;
|
||||
spans->mode = LV_SPAN_MODE_EXPAND;
|
||||
spans->overflow = LV_SPAN_OVERFLOW_CLIP;
|
||||
spans->cache_w = 0;
|
||||
@ -804,15 +826,6 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx)
|
||||
snippet.line_h = lv_font_get_line_height(snippet.font) + line_space;
|
||||
}
|
||||
|
||||
if(spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS) {
|
||||
/* curretn line span txt overflow, don't push */
|
||||
if(txt_pos.y + snippet.line_h - line_space > coords.y2 + 1) {
|
||||
ellipsis_valid = true;
|
||||
is_end_line = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get current span text line info */
|
||||
uint32_t next_ofs = 0;
|
||||
lv_coord_t use_width = 0;
|
||||
@ -820,24 +833,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx)
|
||||
max_w, txt_flag, &use_width, &next_ofs);
|
||||
|
||||
if(isfill) {
|
||||
lv_coord_t next_line_h = snippet.line_h;
|
||||
if(cur_txt[cur_txt_ofs + next_ofs] == '\0') {
|
||||
next_line_h = 0;
|
||||
lv_span_t * next_span = _lv_ll_get_next(&spans->child_ll, cur_span);
|
||||
if(next_span) { /* have the next line */
|
||||
next_line_h = lv_font_get_line_height(lv_span_get_style_text_font(obj, next_span)) + line_space;
|
||||
}
|
||||
}
|
||||
lv_coord_t cur_line_h = max_line_h < snippet.line_h ? snippet.line_h : max_line_h;
|
||||
if(txt_pos.y + cur_line_h + next_line_h - line_space > coords.y2 + 1) { /* for overflow if is end line. */
|
||||
if(cur_txt[cur_txt_ofs + next_ofs] != '\0') {
|
||||
next_ofs = strlen(&cur_txt[cur_txt_ofs]);
|
||||
use_width = lv_txt_get_width(&cur_txt[cur_txt_ofs], next_ofs, snippet.font, snippet.letter_space, txt_flag);
|
||||
ellipsis_valid = spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS ? true : false;
|
||||
is_end_line = true;
|
||||
}
|
||||
}
|
||||
else if(next_ofs > 0 && lv_get_snippet_cnt() > 0) {
|
||||
if(next_ofs > 0 && lv_get_snippet_cnt() > 0) {
|
||||
/* To prevent infinite loops, the _lv_txt_get_next_line() may return incomplete words, */
|
||||
/* This phenomenon should be avoided when lv_get_snippet_cnt() > 0 */
|
||||
if(max_w < use_width) {
|
||||
@ -871,13 +867,35 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx)
|
||||
}
|
||||
}
|
||||
|
||||
/* start current line deal width */
|
||||
/* start current line deal with */
|
||||
|
||||
uint16_t item_cnt = lv_get_snippet_cnt();
|
||||
if(item_cnt == 0) { /* break if stack is empty */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Whether the current line is the end line and does overflow processing */
|
||||
{
|
||||
lv_snippet_t * last_snippet = lv_get_snippet(item_cnt - 1);
|
||||
lv_coord_t next_line_h = last_snippet->line_h;
|
||||
if(last_snippet->txt[last_snippet->bytes] == '\0') {
|
||||
next_line_h = 0;
|
||||
lv_span_t * next_span = _lv_ll_get_next(&spans->child_ll, last_snippet->span);
|
||||
if(next_span) { /* have the next line */
|
||||
next_line_h = lv_font_get_line_height(lv_span_get_style_text_font(obj, next_span)) + line_space;
|
||||
}
|
||||
}
|
||||
if(txt_pos.y + max_line_h + next_line_h - line_space > coords.y2 + 1) { /* for overflow if is end line. */
|
||||
if(last_snippet->txt[last_snippet->bytes] != '\0') {
|
||||
last_snippet->bytes = strlen(last_snippet->txt);
|
||||
last_snippet->txt_w = lv_txt_get_width(last_snippet->txt, last_snippet->bytes, last_snippet->font,
|
||||
last_snippet->letter_space, txt_flag);
|
||||
}
|
||||
ellipsis_valid = spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS ? true : false;
|
||||
is_end_line = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*Go the first visible line*/
|
||||
if(txt_pos.y + max_line_h < clip_area.y1) {
|
||||
goto Next_line_init;
|
||||
@ -965,13 +983,6 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx)
|
||||
}
|
||||
}
|
||||
|
||||
if(ellipsis_valid && i == item_cnt - 1 && pos.x <= ellipsis_width) {
|
||||
for(int ell = 0; ell < 3; ell++) {
|
||||
lv_draw_letter(draw_ctx, &label_draw_dsc, &pos, '.');
|
||||
pos.x = pos.x + dot_letter_w + pinfo->letter_space;
|
||||
}
|
||||
}
|
||||
|
||||
/* draw decor */
|
||||
lv_text_decor_t decor = lv_span_get_style_text_decor(obj, pinfo->span);
|
||||
if(decor != LV_TEXT_DECOR_NONE) {
|
||||
@ -1023,8 +1034,8 @@ 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);
|
||||
lv_obj_refresh_self_size(obj);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -50,6 +50,7 @@ typedef struct {
|
||||
/** Data of label*/
|
||||
typedef struct {
|
||||
lv_obj_t obj;
|
||||
int32_t lines;
|
||||
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 */
|
||||
@ -133,6 +134,13 @@ void lv_spangroup_set_indent(lv_obj_t * obj, lv_coord_t indent);
|
||||
*/
|
||||
void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode);
|
||||
|
||||
/**
|
||||
* Set lines of the spangroup.
|
||||
* @param obj pointer to a spangroup object.
|
||||
* @param lines max lines that can be displayed in LV_SPAN_MODE_BREAK mode. < 0 means no limit.
|
||||
*/
|
||||
void lv_spangroup_set_lines(lv_obj_t * obj, int32_t lines);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@ -185,6 +193,13 @@ lv_coord_t lv_spangroup_get_indent(lv_obj_t * obj);
|
||||
*/
|
||||
lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* get lines of the spangroup.
|
||||
* @param obj pointer to a spangroup object.
|
||||
* @return the lines value.
|
||||
*/
|
||||
int32_t lv_spangroup_get_lines(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* get max line height of all span in the spangroup.
|
||||
* @param obj pointer to a spangroup object.
|
||||
|
Loading…
Reference in New Issue
Block a user