feat(span): add lv_spangroup_bind_span_text and lv_spangroup_set_span_text_fmt

This commit is contained in:
Gabor Kiss-Vamosi
2025-08-21 17:21:56 -03:00
committed by Felipe Neves
parent 3f4117270c
commit 03c48701b7
7 changed files with 197 additions and 7 deletions
+7 -2
View File
@@ -24,6 +24,10 @@ void lv_example_span_1(void)
lv_style_set_border_color(&style, lv_palette_main(LV_PALETTE_ORANGE));
lv_style_set_pad_all(&style, 2);
static lv_subject_t subject;
lv_subject_init_int(&subject, 23);
lv_obj_t * spans = lv_spangroup_create(lv_screen_active());
/* Setting a fixed width and height to LV_SIZE_CONTENT will make the text wrap */
lv_obj_set_width(spans, 300);
@@ -36,14 +40,15 @@ void lv_example_span_1(void)
lv_spangroup_set_overflow(spans, LV_SPAN_OVERFLOW_CLIP);
lv_spangroup_set_indent(spans, 20);
lv_span_t * span = lv_spangroup_add_span(spans);
lv_span_set_text(span, "China is a beautiful country.");
lv_span_set_text(span, "good good study, day day up.");
lv_style_set_text_color(lv_span_get_style(span), lv_palette_main(LV_PALETTE_RED));
lv_style_set_text_decor(lv_span_get_style(span), LV_TEXT_DECOR_UNDERLINE);
lv_style_set_text_opa(lv_span_get_style(span), LV_OPA_50);
span = lv_spangroup_add_span(spans);
lv_span_set_text_static(span, "good good study, day day up.");
lv_spangroup_bind_span_text(spans, span, &subject, "%d users");
#if LV_FONT_MONTSERRAT_24
lv_style_set_text_font(lv_span_get_style(span), &lv_font_montserrat_24);
#endif
+1 -1
View File
@@ -80,7 +80,7 @@ void lv_text_ins(char * txt_buf, uint32_t pos, const char * ins_txt);
void lv_text_cut(char * txt, uint32_t pos, uint32_t len);
/**
* return a new formatted text. Memory will be allocated to store the text.
* Return a new formatted text. Memory will be allocated to store the text.
* @param fmt `printf`-like format
* @param ap items to print
+96
View File
@@ -55,6 +55,17 @@ typedef struct {
const char * value;
} subject_set_string_user_data_t;
typedef struct {
lv_subject_t * subject;
void * element; /**< E.g. span of a span group*/
const char * fmt;
} bind_element_string_t;
typedef struct {
lv_subject_t * subject;
void * element; /**< E.g. min_value of a scale section*/
int32_t * num;
} bind_element_num_t;
typedef struct {
lv_subject_t * subject;
@@ -92,6 +103,10 @@ static void lv_subject_notify_if_changed(lv_subject_t * subject);
static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif
#if LV_USE_SPAN
static void span_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif
#if LV_USE_ARC
static void arc_value_changed_event_cb(lv_event_t * e);
static void arc_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
@@ -779,6 +794,54 @@ lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const
}
#endif /*LV_USE_LABEL*/
#if LV_USE_SPAN
lv_observer_t * lv_spangroup_bind_span_text(lv_obj_t * obj, lv_span_t * span, lv_subject_t * subject, const char * fmt)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
LV_ASSERT_NULL(span);
if(fmt == NULL) {
if(subject->type == LV_SUBJECT_TYPE_INT) {
fmt = "%d";
}
#if LV_USE_FLOAT
else if(subject->type == LV_SUBJECT_TYPE_FLOAT) {
fmt = "%0.1f";
}
#endif
else if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
}
else {
if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER &&
subject->type != LV_SUBJECT_TYPE_INT && subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
}
bind_element_string_t * user_data = lv_zalloc(sizeof(bind_element_string_t));
if(user_data == NULL) {
LV_LOG_WARN("Couldn't allocate user_data");
LV_ASSERT_MALLOC(user_data);
return NULL;
}
user_data->subject = subject;
user_data->element = span;
user_data->fmt = fmt;
lv_observer_t * observer = lv_subject_add_observer_obj(subject, span_text_observer_cb, obj, user_data);
observer->auto_free_user_data = 1;
return observer;
}
#endif /*LV_USE_SPAN*/
#if LV_USE_ARC
lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject)
{
@@ -1090,6 +1153,39 @@ static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subj
#endif /*LV_USE_LABEL*/
#if LV_USE_SPAN
static void span_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
bind_element_string_t * user_data = observer->user_data;
if(user_data->fmt == NULL) {
lv_spangroup_set_span_text(observer->target, user_data->element, subject->value.pointer);
}
else {
switch(subject->type) {
case LV_SUBJECT_TYPE_INT:
lv_spangroup_set_span_text_fmt(observer->target, user_data->element, user_data->fmt, subject->value.num);
break;
#if LV_USE_FLOAT
case LV_SUBJECT_TYPE_FLOAT:
lv_spangroup_set_span_text_fmt(observer->target, user_data->element, user_data->fmt, subject->value.float_v);
break;
#endif
case LV_SUBJECT_TYPE_STRING:
case LV_SUBJECT_TYPE_POINTER:
lv_spangroup_set_span_text_fmt(observer->target, user_data->element, user_data->fmt, subject->value.pointer);
break;
default:
return;
}
}
}
#endif /*LV_USE_SPAN*/
#if LV_USE_ARC
static void arc_value_changed_event_cb(lv_event_t * e)
+18
View File
@@ -545,6 +545,24 @@ lv_observer_t * lv_obj_bind_checked(lv_obj_t * obj, lv_subject_t * subject);
lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt);
#endif
#if LV_USE_LABEL
/**
* Bind an integer, string, or pointer Subject to a Label.
* @param obj pointer to Spangroup
* @param span pointer to Span
* @param subject pointer to Subject
* @param fmt optional printf-like format string with 1 format specifier (e.g. "%d °C")
* or NULL to bind to the value directly.
* @return pointer to newly-created Observer
* @note `fmt == NULL` can be used only with string and pointer Subjects.
* @note If Subject is a pointer and `fmt == NULL`, pointer must point
* to a `\0` terminated string.
*/
lv_observer_t * lv_spangroup_bind_span_text(lv_obj_t * obj, lv_span_t * span, lv_subject_t * subject, const char * fmt);
#endif
#if LV_USE_ARC
/**
* Bind an integer subject to an Arc's value.
+8 -4
View File
@@ -84,26 +84,28 @@ lv_obj_t * lv_label_create(lv_obj_t * parent);
* Set a new text for a label. Memory will be allocated to store the text by the label.
* @param obj pointer to a label object
* @param text '\0' terminated character string. NULL to refresh with the current text.
* @note If `LV_USE_ARABIC_PERSIAN_CHARS` is enabled the text will be modified to have the correct Arabic
* characters in it.
*/
void lv_label_set_text(lv_obj_t * obj, const char * text);
/**
* Set a new formatted text for a label. Memory will be allocated to store the text by the label.
* @param obj pointer to a label object
* @param fmt `printf`-like format
*
* @param fmt `printf`-like format string
* Example:
* @code
* lv_label_set_text_fmt(label1, "%d user", user_num);
* @endcode
* @note It ignores `LV_USE_ARABIC_PERSIAN_CHARS`
*/
void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) LV_FORMAT_ATTRIBUTE(2, 3);
/**
* Set a new formatted text for a label. Memory will be allocated to store the text by the label.
* @param obj pointer to a label object
* @param fmt `printf`-like format
* @param args variadic argments list
* @param fmt `printf`-like format string
* @param args variadic arguments list
*
* Example:
* @code
@@ -112,6 +114,7 @@ void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) LV_FORMAT_ATTR
* lv_label_set_text_vfmt(label1, fmt, args);
* va_end(args);
* @endcode
* @note It ignores `LV_USE_ARABIC_PERSIAN_CHARS`
*/
void lv_label_set_text_vfmt(lv_obj_t * obj, const char * fmt, va_list args);
@@ -120,6 +123,7 @@ void lv_label_set_text_vfmt(lv_obj_t * obj, const char * fmt, va_list args);
* has to be 'alive' while the label exists.
* @param obj pointer to a label object
* @param text pointer to a text. NULL to refresh with the current text.
* @note It ignores `LV_USE_ARABIC_PERSIAN_CHARS`
*/
void lv_label_set_text_static(lv_obj_t * obj, const char * text);
+47
View File
@@ -199,6 +199,29 @@ void lv_span_set_text(lv_span_t * span, const char * text)
#endif
}
void lv_span_set_text_fmt(lv_span_t * span, const char * fmt, ...)
{
if(span == NULL || fmt == NULL) {
return;
}
va_list args;
va_start(args, fmt);
char * text = lv_text_set_text_vfmt(fmt, args);
LV_ASSERT_MALLOC(text);
if(text == NULL) return;
va_end(args);
if(span->txt == NULL && span->static_flag) {
lv_free(span->txt);
}
span->static_flag = 0;
span->txt = text;
}
void lv_spangroup_set_span_text(lv_obj_t * obj, lv_span_t * span, const char * text)
{
lv_span_set_text(span, text);
@@ -234,6 +257,30 @@ void lv_spangroup_set_span_text_static(lv_obj_t * obj, lv_span_t * span, const c
lv_spangroup_refresh(obj);
}
void lv_spangroup_set_span_text_fmt(lv_obj_t * obj, lv_span_t * span, const char * fmt, ...)
{
if(span == NULL || fmt == NULL) {
return;
}
va_list args;
va_start(args, fmt);
char * text = lv_text_set_text_vfmt(fmt, args);
LV_ASSERT_MALLOC(text);
if(text == NULL) return;
va_end(args);
if(span->txt == NULL && span->static_flag) {
lv_free(span->txt);
}
span->static_flag = 0;
span->txt = text;
lv_spangroup_refresh(obj);
}
void lv_spangroup_set_span_style(lv_obj_t * obj, lv_span_t * span, const lv_style_t * style)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
+20
View File
@@ -91,6 +91,17 @@ void lv_spangroup_delete_span(lv_obj_t * obj, lv_span_t * span);
*/
void lv_span_set_text(lv_span_t * span, const char * text);
/**
* Set a new text for a span using a printf-like formatting string.
* Memory will be allocated to store the text by the span.
* As the spangroup is not passed a redraw (invalidation) can't be triggered automatically.
* Therefore `lv_spangroup_refresh(spangroup)` needs to be called manually,
* @param span pointer to a span.
* @param fmt `printf`-like format string
*/
void lv_span_set_text_fmt(lv_span_t * span, const char * fmt, ...);
/**
* Set a static text. It will not be saved by the span so the 'text' variable
* has to be 'alive' while the span exist.
@@ -118,6 +129,15 @@ void lv_spangroup_set_span_text(lv_obj_t * obj, lv_span_t * span, const char * t
*/
void lv_spangroup_set_span_text_static(lv_obj_t * obj, lv_span_t * span, const char * text);
/**
* Set a new text for a span using a printf-like formatting string.
* Memory will be allocated to store the text by the span.
* @param obj pointer to a spangroup widget.
* @param span pointer to a span.
* @param fmt `printf`-like format string
*/
void lv_spangroup_set_span_text_fmt(lv_obj_t * obj, lv_span_t * span, const char * fmt, ...);
/**
* Set a static text. It will not be saved by the span so the 'text' variable
* has to be 'alive' while the span exist.