feat(label): add lv_label_set_max_lines() (#10143)

This commit is contained in:
Niklas Fiekas
2026-05-19 20:44:33 +02:00
committed by GitHub
parent b7bfbd7cfa
commit 95fa415f5a
9 changed files with 80 additions and 4 deletions
+1 -1
View File
@@ -19,7 +19,7 @@
extern const lv_property_name_t lv_dropdown_property_names[9];
extern const lv_property_name_t lv_image_property_names[11];
extern const lv_property_name_t lv_keyboard_property_names[4];
extern const lv_property_name_t lv_label_property_names[4];
extern const lv_property_name_t lv_label_property_names[5];
extern const lv_property_name_t lv_led_property_names[2];
extern const lv_property_name_t lv_line_property_names[1];
extern const lv_property_name_t lv_menu_property_names[2];
+18 -2
View File
@@ -58,8 +58,9 @@ typedef enum {
enum _lv_property_label_id_t {
LV_PROPERTY_ID(LABEL, TEXT, LV_PROPERTY_TYPE_TEXT, 0),
LV_PROPERTY_ID(LABEL, LONG_MODE, LV_PROPERTY_TYPE_INT, 1),
LV_PROPERTY_ID(LABEL, TEXT_SELECTION_START, LV_PROPERTY_TYPE_INT, 2),
LV_PROPERTY_ID(LABEL, TEXT_SELECTION_END, LV_PROPERTY_TYPE_INT, 3),
LV_PROPERTY_ID(LABEL, MAX_LINES, LV_PROPERTY_TYPE_INT, 2),
LV_PROPERTY_ID(LABEL, TEXT_SELECTION_START, LV_PROPERTY_TYPE_INT, 3),
LV_PROPERTY_ID(LABEL, TEXT_SELECTION_END, LV_PROPERTY_TYPE_INT, 4),
LV_PROPERTY_LABEL_END,
};
#endif
@@ -136,6 +137,14 @@ void lv_label_set_text_static(lv_obj_t * obj, const char * text);
*/
void lv_label_set_long_mode(lv_obj_t * obj, lv_label_long_mode_t long_mode);
/**
* Set the maximum number of lines that the label should display in
* `LV_LABEL_LONG_MODE_WRAP` and `LV_LABEL_LONG_MODE_DOTS` mode.
* @param obj pointer to a label object
* @param lines number of lines to display (unlimited if not positive)
*/
void lv_label_set_max_lines(lv_obj_t * obj, int32_t lines);
/**
* Set where text selection should start
* @param obj pointer to a label object
@@ -189,6 +198,13 @@ char * lv_label_get_text(const lv_obj_t * obj);
*/
lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * obj);
/**
* Get the maximum number of lines that a label should display
* @param obj pointer to a label object
* @return the maximum number of lines, if positive
*/
int32_t lv_label_get_max_lines(const lv_obj_t * obj);
/**
* Get the relative x and y coordinates of a letter
* @param obj pointer to a label object
@@ -29,6 +29,10 @@ class LVLabel(LVObject):
"""Offset where bytes have been replaced with dots"""
return int(self._wv.safe_field("dot_begin", 0))
@property
def max_lines(self):
return int(self._wv.safe_field("max_lines", 0))
@property
def sel_start(self):
return int(self._wv.safe_field("sel_start", 0))
@@ -88,6 +92,7 @@ class LVLabel(LVObject):
d["text"] = self.text
d["translation_tag"] = self.translation_tag
d["dot_begin"] = self.dot_begin
d["max_lines"] = self.max_lines
d["sel_start"] = self.sel_start
d["sel_end"] = self.sel_end
d["size_cache"] = self.size_cache
+25
View File
@@ -76,6 +76,11 @@ static const lv_property_ops_t lv_label_properties[] = {
.setter = lv_label_set_long_mode,
.getter = lv_label_get_long_mode,
},
{
.id = LV_PROPERTY_LABEL_MAX_LINES,
.setter = lv_label_set_max_lines,
.getter = lv_label_get_max_lines,
},
{
.id = LV_PROPERTY_LABEL_TEXT_SELECTION_START,
.setter = lv_label_set_text_selection_start,
@@ -225,6 +230,14 @@ void lv_label_set_long_mode(lv_obj_t * obj, lv_label_long_mode_t long_mode)
lv_label_mark_need_refr_text(obj);
}
void lv_label_set_max_lines(lv_obj_t * obj, int32_t lines)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_label_t * label = (lv_label_t *)obj;
label->max_lines = lines;
lv_label_refr_text(obj);
}
void lv_label_set_text_selection_start(lv_obj_t * obj, uint32_t index)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
@@ -284,6 +297,13 @@ lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * obj)
return label->long_mode;
}
int32_t lv_label_get_max_lines(const lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
const lv_label_t * label = (const lv_label_t *)obj;
return label->max_lines;
}
void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t * pos)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
@@ -840,6 +860,11 @@ static void lv_label_event(const lv_obj_class_t * class_p, lv_event_t * e)
lv_text_get_size_attributes(&label->size_cache, label->text, font, &attributes);
lv_label_set_dots(obj, dot_begin);
if(label->max_lines > 0) {
label->size_cache.y = LV_MIN(label->size_cache.y,
lv_font_get_line_height(font) * label->max_lines + line_space * (label->max_lines - 1));
}
lv_text_leading_trim_t leading_trim =
lv_obj_get_style_text_leading_trim(obj, LV_PART_MAIN);
if(leading_trim != LV_TEXT_LEADING_TRIM_NONE) {
+1
View File
@@ -36,6 +36,7 @@ struct _lv_label_t {
#endif /*LV_USE_TRANSLATION*/
char dot[LV_LABEL_DOT_NUM + 1]; /**< Bytes that have been replaced with dots */
uint32_t dot_begin; /**< Offset where bytes have been replaced with dots */
int32_t max_lines;
#if LV_LABEL_LONG_TXT_HINT
lv_draw_label_hint_t hint;
+2 -1
View File
@@ -14,8 +14,9 @@
* Generated code from properties.py
*/
/* *INDENT-OFF* */
const lv_property_name_t lv_label_property_names[4] = {
const lv_property_name_t lv_label_property_names[5] = {
{"long_mode", LV_PROPERTY_LABEL_LONG_MODE,},
{"max_lines", LV_PROPERTY_LABEL_MAX_LINES,},
{"text", LV_PROPERTY_LABEL_TEXT,},
{"text_selection_end", LV_PROPERTY_LABEL_TEXT_SELECTION_END,},
{"text_selection_start", LV_PROPERTY_LABEL_TEXT_SELECTION_START,},
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

+28
View File
@@ -773,6 +773,34 @@ void test_label_long_mode_clip(void)
TEST_ASSERT_EQUAL_SCREENSHOT(buf);
}
void test_label_max_lines(void)
{
lv_obj_clean(lv_screen_active());
lv_obj_t * parent = lv_obj_create(lv_screen_active());
lv_obj_set_size(parent, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(parent, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_text_line_space(parent, 10, LV_PART_MAIN);
const char * texts[] = {
"Fits in single line",
"Length such that exactly three lines will be needed for this text",
"Text\nwith line breaks\nwhere display will need more than three lines",
};
for(int i = 0; i < 3; i++) {
lv_obj_t * test_label = lv_label_create(parent);
lv_obj_set_width(test_label, 200);
lv_obj_set_style_bg_color(test_label, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_label, LV_OPA_100, LV_PART_MAIN);
lv_label_set_long_mode(test_label, LV_LABEL_LONG_MODE_DOTS);
lv_label_set_text(test_label, texts[i]);
lv_label_set_max_lines(test_label, 3);
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/label_max_lines.png");
}
void test_label_wrap_mode_clip(void)
{
lv_obj_clean(lv_screen_active());