feat(observer): add float subject type (#8388)

This commit is contained in:
Gabor Kiss-Vamosi
2025-06-19 11:46:50 +02:00
committed by GitHub
parent 1ef1d23342
commit ae0a3bc822
10 changed files with 311 additions and 16 deletions
@@ -17,7 +17,7 @@ This implementation consists of:
:Subjects: (in global memory or heap) are "logic packages", each containing the :Subjects: (in global memory or heap) are "logic packages", each containing the
value being "observed" and its type (integer (``int32_t``), a string, a value being "observed" and its type (integer (``int32_t``), a string, a
pointer, an :cpp:type:`lv_color_t`, or a group); pointer, an :cpp:type:`lv_color_t`, a :cpp_type:`float`, or a group);
:Observers: (zero or more per Subject, always dynamically-allocated) are always :Observers: (zero or more per Subject, always dynamically-allocated) are always
attached to exactly one Subject, and provide user-defined notifications attached to exactly one Subject, and provide user-defined notifications
@@ -114,6 +114,7 @@ To initialize a Subject use ``lv_subject_init_<type>(&subject, params, init_valu
The following initialization functions exist, one for each of the Subject types: The following initialization functions exist, one for each of the Subject types:
:Integer: void :cpp:expr:`lv_subject_init_int(subject, int_value)` :Integer: void :cpp:expr:`lv_subject_init_int(subject, int_value)`
:Float: void :cpp:expr:`lv_subject_init_float(subject, float_value)`
:String: void :cpp:expr:`lv_subject_init_string(subject, buf, prev_buf, buf_size, initial_string)` :String: void :cpp:expr:`lv_subject_init_string(subject, buf, prev_buf, buf_size, initial_string)`
:Pointer: void :cpp:expr:`lv_subject_init_pointer(subject, ptr)` :Pointer: void :cpp:expr:`lv_subject_init_pointer(subject, ptr)`
:Color: void :cpp:expr:`lv_subject_init_color(subject, color)` :Color: void :cpp:expr:`lv_subject_init_color(subject, color)`
@@ -141,6 +142,7 @@ The following functions are used to get a Subject's current value:
:Integer: int32_t :cpp:expr:`lv_subject_get_int(subject)` :Integer: int32_t :cpp:expr:`lv_subject_get_int(subject)`
:Float: float :cpp:expr:`lv_subject_get_float(subject)`
:String: const char * :cpp:expr:`lv_subject_get_string(subject)` :String: const char * :cpp:expr:`lv_subject_get_string(subject)`
:Pointer: const void * :cpp:expr:`lv_subject_get_pointer(subject)` :Pointer: const void * :cpp:expr:`lv_subject_get_pointer(subject)`
:Color: lv_color_t :cpp:expr:`lv_subject_get_color(subject)` :Color: lv_color_t :cpp:expr:`lv_subject_get_color(subject)`
@@ -153,6 +155,7 @@ The following functions are used to get a Subject's previous value:
:Integer: int32_t :cpp:expr:`lv_subject_get_previous_int(subject)` :Integer: int32_t :cpp:expr:`lv_subject_get_previous_int(subject)`
:Float: float :cpp:expr:`lv_subject_get_previous_float(subject)`
:String: const char * :cpp:expr:`lv_subject_get_previous_string(subject)` :String: const char * :cpp:expr:`lv_subject_get_previous_string(subject)`
:Pointer: const void * :cpp:expr:`lv_subject_get_previous_pointer(subject)` :Pointer: const void * :cpp:expr:`lv_subject_get_previous_pointer(subject)`
:Color: lv_color_t :cpp:expr:`lv_subject_get_previous_color(subject)` :Color: lv_color_t :cpp:expr:`lv_subject_get_previous_color(subject)`
@@ -492,11 +495,14 @@ printf-like format specifier and be one of the following:
cross-platform equivalent where ``xx`` can be ``8``, cross-platform equivalent where ``xx`` can be ``8``,
``16``, ``32`` or ``64``, depending on the platform). ``16``, ``32`` or ``64``, depending on the platform).
If NULL is passed for the ``format_string`` argument: :float Subject: "%f" format specifier, or e.g. "%0.2f" to display two digits after the decimal point.
If ``NULL`` is passed for the ``format_string`` argument:
:string or pointer Subject: Updates expect the pointer to point to a NUL-terminated string. :string or pointer Subject: Updates expect the pointer to point to a NUL-terminated string.
:integer Subject: The Label will simply display the number. Equivalent to "%d".
:integer Subject: The Label will display an empty string (i.e. nothing). :float Subject: The Label will display the value with "%0.1f" format string.
**Example:** "%d |deg|\C" **Example:** "%d |deg|\C"
@@ -509,6 +515,9 @@ value directly. Note that this is a two-way binding (Subject <===> Widget) so a
user's direct interaction with the Arc Widget updates the Subject's value and vice user's direct interaction with the Arc Widget updates the Subject's value and vice
versa. (Requires :c:macro:`LV_USE_ARC` to be configured to ``1``.) versa. (Requires :c:macro:`LV_USE_ARC` to be configured to ``1``.)
It support integer and float subjects.
- :cpp:expr:`lv_arc_bind_value(arc, &subject)` - :cpp:expr:`lv_arc_bind_value(arc, &subject)`
@@ -520,6 +529,8 @@ value directly. Note that this is a two-way binding (Subject <===> Widget) so a
user's direct interaction with the Slider Widget updates the Subject's value and vice user's direct interaction with the Slider Widget updates the Subject's value and vice
versa. (Requires :c:macro:`LV_USE_SLIDER` to be configured to ``1``.) versa. (Requires :c:macro:`LV_USE_SLIDER` to be configured to ``1``.)
It support integer and float subjects.
- :cpp:expr:`lv_slider_bind_value(slider, &subject)` - :cpp:expr:`lv_slider_bind_value(slider, &subject)`
@@ -531,6 +542,8 @@ value directly. Note that this is a two-way binding (Subject <===> Widget) so a
user's direct interaction with the Slider Widget updates the Subject's value and vice user's direct interaction with the Slider Widget updates the Subject's value and vice
versa. (Requires :c:macro:`LV_USE_ROLLER` to be configured to ``1``.) versa. (Requires :c:macro:`LV_USE_ROLLER` to be configured to ``1``.)
It support only integer subjects.
- :cpp:expr:`lv_roller_bind_value(roller, &subject)` - :cpp:expr:`lv_roller_bind_value(roller, &subject)`
@@ -542,6 +555,8 @@ value directly. Note that this is a two-way binding (Subject <===> Widget) so a
user's direct interaction with the Drop-Down Widget updates the Subject's value and user's direct interaction with the Drop-Down Widget updates the Subject's value and
vice versa. (Requires :c:macro:`LV_USE_DROPDOWN` to be configured to ``1``.) vice versa. (Requires :c:macro:`LV_USE_DROPDOWN` to be configured to ``1``.)
It support only integer subjects.
- :cpp:expr:`lv_dropdown_bind_value(dropdown, &subject)` - :cpp:expr:`lv_dropdown_bind_value(dropdown, &subject)`
+97 -7
View File
@@ -158,6 +158,51 @@ int32_t lv_subject_get_previous_int(lv_subject_t * subject)
return subject->prev_value.num; return subject->prev_value.num;
} }
#if LV_USE_FLOAT
void lv_subject_init_float(lv_subject_t * subject, float value)
{
lv_memzero(subject, sizeof(lv_subject_t));
subject->type = LV_SUBJECT_TYPE_FLOAT;
subject->value.float_v = value;
subject->prev_value.float_v = value;
lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
}
void lv_subject_set_float(lv_subject_t * subject, float value)
{
if(subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_FLOAT");
return;
}
subject->prev_value.float_v = subject->value.float_v;
subject->value.float_v = value;
lv_subject_notify_if_changed(subject);
}
float lv_subject_get_float(lv_subject_t * subject)
{
if(subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_FLOAT");
return 0;
}
return subject->value.float_v;
}
float lv_subject_get_previous_float(lv_subject_t * subject)
{
if(subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_FLOAT");
return 0;
}
return subject->prev_value.float_v;
}
#endif /*LV_USE_FLOAT*/
void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value) void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value)
{ {
lv_memzero(subject, sizeof(lv_subject_t)); lv_memzero(subject, sizeof(lv_subject_t));
@@ -683,6 +728,11 @@ lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const
if(subject->type == LV_SUBJECT_TYPE_INT) { if(subject->type == LV_SUBJECT_TYPE_INT) {
fmt = "%d"; 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) { else if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type); LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL; return NULL;
@@ -690,7 +740,7 @@ lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const
} }
else { else {
if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER && if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER &&
subject->type != LV_SUBJECT_TYPE_INT) { subject->type != LV_SUBJECT_TYPE_INT && subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type); LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL; return NULL;
} }
@@ -707,7 +757,7 @@ lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject)
LV_ASSERT_NULL(subject); LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj); LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) { if(subject->type != LV_SUBJECT_TYPE_INT && subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type); LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL; return NULL;
} }
@@ -725,7 +775,7 @@ lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject)
LV_ASSERT_NULL(subject); LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj); LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) { if(subject->type != LV_SUBJECT_TYPE_INT && subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type); LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL; return NULL;
} }
@@ -937,6 +987,13 @@ static void lv_subject_notify_if_changed(lv_subject_t * subject)
lv_subject_notify(subject); lv_subject_notify(subject);
} }
break; break;
#if LV_USE_FLOAT
case LV_SUBJECT_TYPE_FLOAT :
if(subject->value.float_v != subject->prev_value.float_v) {
lv_subject_notify(subject);
}
break;
#endif
case LV_SUBJECT_TYPE_GROUP : case LV_SUBJECT_TYPE_GROUP :
case LV_SUBJECT_TYPE_POINTER : case LV_SUBJECT_TYPE_POINTER :
/* Always notify as we don't know how to compare this */ /* Always notify as we don't know how to compare this */
@@ -970,6 +1027,11 @@ static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subj
case LV_SUBJECT_TYPE_INT: case LV_SUBJECT_TYPE_INT:
lv_label_set_text_fmt(observer->target, fmt, subject->value.num); lv_label_set_text_fmt(observer->target, fmt, subject->value.num);
break; break;
#if LV_USE_FLOAT
case LV_SUBJECT_TYPE_FLOAT:
lv_label_set_text_fmt(observer->target, fmt, subject->value.float_v);
break;
#endif
case LV_SUBJECT_TYPE_STRING: case LV_SUBJECT_TYPE_STRING:
case LV_SUBJECT_TYPE_POINTER: case LV_SUBJECT_TYPE_POINTER:
lv_label_set_text_fmt(observer->target, fmt, subject->value.pointer); lv_label_set_text_fmt(observer->target, fmt, subject->value.pointer);
@@ -989,12 +1051,26 @@ static void arc_value_changed_event_cb(lv_event_t * e)
lv_obj_t * arc = lv_event_get_current_target(e); lv_obj_t * arc = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e); lv_subject_t * subject = lv_event_get_user_data(e);
lv_subject_set_int(subject, lv_arc_get_value(arc)); if(subject->type == LV_SUBJECT_TYPE_INT) {
lv_subject_set_int(subject, lv_arc_get_value(arc));
}
#if LV_USE_FLOAT
else {
lv_subject_set_float(subject, (float)lv_arc_get_value(arc));
}
#endif
} }
static void arc_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject) static void arc_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{ {
lv_arc_set_value(observer->target, subject->value.num); if(subject->type == LV_SUBJECT_TYPE_INT) {
lv_arc_set_value(observer->target, subject->value.num);
}
#if LV_USE_FLOAT
else {
lv_arc_set_value(observer->target, (int32_t)subject->value.float_v);
}
#endif
} }
#endif /*LV_USE_ARC*/ #endif /*LV_USE_ARC*/
@@ -1006,12 +1082,26 @@ static void slider_value_changed_event_cb(lv_event_t * e)
lv_obj_t * slider = lv_event_get_current_target(e); lv_obj_t * slider = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e); lv_subject_t * subject = lv_event_get_user_data(e);
lv_subject_set_int(subject, lv_slider_get_value(slider)); if(subject->type == LV_SUBJECT_TYPE_INT) {
lv_subject_set_int(subject, lv_slider_get_value(slider));
}
#if LV_USE_FLOAT
else {
lv_subject_set_float(subject, (float)lv_slider_get_value(slider));
}
#endif
} }
static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject) static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{ {
lv_slider_set_value(observer->target, subject->value.num, LV_ANIM_OFF); if(subject->type == LV_SUBJECT_TYPE_INT) {
lv_slider_set_value(observer->target, subject->value.num, LV_ANIM_OFF);
}
#if LV_USE_FLOAT
else {
lv_slider_set_value(observer->target, (int32_t)subject->value.float_v, LV_ANIM_OFF);
}
#endif
} }
#endif /*LV_USE_SLIDER*/ #endif /*LV_USE_SLIDER*/
+40 -4
View File
@@ -32,10 +32,11 @@ typedef enum {
LV_SUBJECT_TYPE_INVALID = 0, /**< indicates Subject not initialized yet */ LV_SUBJECT_TYPE_INVALID = 0, /**< indicates Subject not initialized yet */
LV_SUBJECT_TYPE_NONE = 1, /**< a null value like None or NILt */ LV_SUBJECT_TYPE_NONE = 1, /**< a null value like None or NILt */
LV_SUBJECT_TYPE_INT = 2, /**< an int32_t */ LV_SUBJECT_TYPE_INT = 2, /**< an int32_t */
LV_SUBJECT_TYPE_POINTER = 3, /**< a void pointer */ LV_SUBJECT_TYPE_FLOAT = 3, /**< a float, requires `LV_USE_FLOAT 1` */
LV_SUBJECT_TYPE_COLOR = 4, /**< an lv_color_t */ LV_SUBJECT_TYPE_POINTER = 4, /**< a void pointer */
LV_SUBJECT_TYPE_GROUP = 5, /**< an array of Subjects */ LV_SUBJECT_TYPE_COLOR = 5, /**< an lv_color_t */
LV_SUBJECT_TYPE_STRING = 6, /**< a char pointer */ LV_SUBJECT_TYPE_GROUP = 6, /**< an array of Subjects */
LV_SUBJECT_TYPE_STRING = 7, /**< a char pointer */
} lv_subject_type_t; } lv_subject_type_t;
/** /**
@@ -45,6 +46,9 @@ typedef union {
int32_t num; /**< Integer number (opacity, enums, booleans or "normal" numbers) */ int32_t num; /**< Integer number (opacity, enums, booleans or "normal" numbers) */
const void * pointer; /**< Constant pointer (string buffer, format string, font, cone text, etc.) */ const void * pointer; /**< Constant pointer (string buffer, format string, font, cone text, etc.) */
lv_color_t color; /**< Color */ lv_color_t color; /**< Color */
#if LV_USE_FLOAT
float float_v; /**< Floating point value*/
#endif
} lv_subject_value_t; } lv_subject_value_t;
/** /**
@@ -100,6 +104,38 @@ int32_t lv_subject_get_int(lv_subject_t * subject);
*/ */
int32_t lv_subject_get_previous_int(lv_subject_t * subject); int32_t lv_subject_get_previous_int(lv_subject_t * subject);
#if LV_USE_FLOAT
/**
* Initialize an float-type Subject.
* @param subject pointer to Subject
* @param value initial value
*/
void lv_subject_init_float(lv_subject_t * subject, float value);
/**
* Set value of an float Subject and notify Observers.
* @param subject pointer to Subject
* @param value new value
*/
void lv_subject_set_float(lv_subject_t * subject, float value);
/**
* Get current value of an float Subject.
* @param subject pointer to Subject
* @return current value
*/
float lv_subject_get_float(lv_subject_t * subject);
/**
* Get previous value of an float Subject.
* @param subject pointer to Subject
* @return current value
*/
float lv_subject_get_previous_float(lv_subject_t * subject);
#endif /*LV_USE_FLOAT*/
/** /**
* Initialize a string-type Subject. * Initialize a string-type Subject.
* @param subject pointer to Subject * @param subject pointer to Subject
+3
View File
@@ -460,6 +460,9 @@ static void process_subject_element(lv_xml_parser_state_t * state, const char *
lv_subject_t * subject = lv_zalloc(sizeof(lv_subject_t)); lv_subject_t * subject = lv_zalloc(sizeof(lv_subject_t));
if(lv_streq(type, "int")) lv_subject_init_int(subject, lv_xml_atoi(value)); if(lv_streq(type, "int")) lv_subject_init_int(subject, lv_xml_atoi(value));
#if LV_USE_FLOAT
else if(lv_streq(type, "float")) lv_subject_init_float(subject, lv_xml_atof(value));
#endif
else if(lv_streq(type, "color")) lv_subject_init_color(subject, lv_xml_to_color(value)); else if(lv_streq(type, "color")) lv_subject_init_color(subject, lv_xml_to_color(value));
else if(lv_streq(type, "string")) { else if(lv_streq(type, "string")) {
/*Simple solution for now. Will be improved later*/ /*Simple solution for now. Will be improved later*/
+67
View File
@@ -109,6 +109,7 @@ int32_t lv_xml_atoi_split(const char ** str, char delimiter)
} }
result = result * sign; result = result * sign;
while(*s != delimiter && *s != '\0') s++; /*Make sure to find the delimiter*/
if(*s != '\0') s++; /*Skip the delimiter*/ if(*s != '\0') s++; /*Skip the delimiter*/
*str = s; *str = s;
@@ -120,6 +121,72 @@ int32_t lv_xml_atoi(const char * str)
return lv_xml_atoi_split(&str, '\0'); return lv_xml_atoi_split(&str, '\0');
} }
#if LV_USE_FLOAT
float lv_xml_atof_split(const char ** str, char delimiter)
{
const char * s = *str;
float result = 0.0f;
int sign = 1;
/* Skip leading whitespace */
while(*s == ' ' || *s == '\t') s++;
/* Handle optional sign */
if(*s == '-') {
sign = -1;
s++;
}
else if(*s == '+') {
s++;
}
/* Convert the integer part */
while(*s != delimiter && *s != '.' && *s != '\0') {
if(*s >= '0' && *s <= '9') {
float digit = *s - '0';
result = result * 10.0f + digit;
s++;
}
else {
break; /* Non-digit character */
}
}
/* Convert the fractional part */
if(*s == '.') {
s++; /* Skip the decimal point */
float fraction = 0.0f;
float divisor = 10.0f;
while(*s != delimiter && *s != '\0') {
if(*s >= '0' && *s <= '9') {
float digit = *s - '0';
fraction += digit / divisor;
divisor *= 10.0f;
s++;
}
else {
break; /* Non-digit character */
}
}
result += fraction;
}
result = result * sign;
while(*s != delimiter && *s != '\0') s++; /*Make sure to find the delimiter*/
if(*s != '\0') s++; /*Skip the delimiter*/
*str = s;
return result;
}
float lv_xml_atof(const char * str)
{
return lv_xml_atof_split(&str, '\0');
}
#endif
int32_t lv_xml_strtol(const char * str, char ** endptr, int32_t base) int32_t lv_xml_strtol(const char * str, char ** endptr, int32_t base)
{ {
const char * s = str; const char * s = str;
+13 -1
View File
@@ -26,7 +26,6 @@ const char * lv_xml_get_value_of(const char ** attrs, const char * name);
int32_t lv_xml_atoi(const char * str); int32_t lv_xml_atoi(const char * str);
/** /**
* Convert sections of a string to int. * Convert sections of a string to int.
* The end of the string is indicated by the `delimiter`. * The end of the string is indicated by the `delimiter`.
@@ -36,6 +35,19 @@ int32_t lv_xml_atoi(const char * str);
*/ */
int32_t lv_xml_atoi_split(const char ** str, char delimiter); int32_t lv_xml_atoi_split(const char ** str, char delimiter);
#if LV_USE_FLOAT
float lv_xml_atof(const char * str);
/**
* Convert sections of a string to float.
* The end of the string is indicated by the `delimiter`.
* @param str pointer to a string, it will point to the character after the delimiter
* @param delimiter a character to indicate the end of the float
* @return the float before the next delimiter
*/
float lv_xml_atof_split(const char ** str, char delimiter);
#endif
lv_color_t lv_xml_to_color(const char * str); lv_color_t lv_xml_to_color(const char * str);
/** /**
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

+57
View File
@@ -192,6 +192,52 @@ void test_observer_int(void)
lv_observer_remove(basic_observer); lv_observer_remove(basic_observer);
} }
void test_observer_float(void)
{
static lv_subject_t subject;
lv_subject_init_float(&subject, 5.25);
lv_observer_t * basic_observer =
lv_subject_add_observer(&subject, observer_basic, NULL);
TEST_ASSERT_EQUAL_FLOAT(5.25, lv_subject_get_float(&subject));
TEST_ASSERT_EQUAL_FLOAT(5.25, lv_subject_get_previous_float(&subject));
TEST_ASSERT_EQUAL(1, observer_called);
lv_subject_set_float(&subject, 10.5);
TEST_ASSERT_EQUAL_FLOAT(10.5, lv_subject_get_float(&subject));
TEST_ASSERT_EQUAL_FLOAT(5.25, lv_subject_get_previous_float(&subject));
TEST_ASSERT_EQUAL(2, observer_called);
lv_subject_set_float(&subject, 15.75);
TEST_ASSERT_EQUAL_FLOAT(15.75, lv_subject_get_float(&subject));
TEST_ASSERT_EQUAL_FLOAT(10.5, lv_subject_get_previous_float(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
/* Observer shouldn't be called if value is the same */
lv_subject_set_float(&subject, 15.75);
TEST_ASSERT_EQUAL_FLOAT(15.75, lv_subject_get_float(&subject));
TEST_ASSERT_EQUAL_FLOAT(15.75, lv_subject_get_previous_float(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
/*Ignore incorrect types*/
lv_subject_set_pointer(&subject, NULL);
TEST_ASSERT_EQUAL_FLOAT(15.75, lv_subject_get_float(&subject));
TEST_ASSERT_EQUAL_FLOAT(15.75, lv_subject_get_previous_float(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
lv_subject_set_color(&subject, lv_color_black());
TEST_ASSERT_EQUAL_FLOAT(15.75, lv_subject_get_float(&subject));
TEST_ASSERT_EQUAL_FLOAT(15.75, lv_subject_get_previous_float(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
lv_subject_copy_string(&subject, "hello");
TEST_ASSERT_EQUAL_FLOAT(15.75, lv_subject_get_float(&subject));
TEST_ASSERT_EQUAL_FLOAT(15.75, lv_subject_get_previous_float(&subject));
TEST_ASSERT_EQUAL(3, observer_called);
lv_observer_remove(basic_observer);
}
void test_observer_string(void) void test_observer_string(void)
{ {
char buf_current[32]; char buf_current[32];
@@ -756,6 +802,17 @@ void test_observer_label_text_normal(void)
observer = lv_label_bind_text(obj, &subject_int, NULL); observer = lv_label_bind_text(obj, &subject_int, NULL);
TEST_ASSERT_EQUAL_STRING("10", lv_label_get_text(obj)); TEST_ASSERT_EQUAL_STRING("10", lv_label_get_text(obj));
/*Bind it with "%0.1f" if NULL is passed*/
static lv_subject_t subject_float;
lv_subject_init_float(&subject_float, 10.5);
observer = lv_label_bind_text(obj, &subject_float, NULL);
TEST_ASSERT_EQUAL_STRING("10.5", lv_label_get_text(obj));
/*Bind it with "%0.1f" if NULL is passed*/
lv_subject_set_float(&subject_float, 81.5);
observer = lv_label_bind_text(obj, &subject_float, "Value: %0.2f");
TEST_ASSERT_EQUAL_STRING("Value: 81.50", lv_label_get_text(obj));
/*Bind to string*/ /*Bind to string*/
static char buf[32]; static char buf[32];
static lv_subject_t subject_string; static lv_subject_t subject_string;
+15
View File
@@ -35,6 +35,7 @@ void test_xml_label_with_attrs(void)
lv_subject_init_int(&s1, 20); lv_subject_init_int(&s1, 20);
lv_xml_register_subject(NULL, "s1", &s1); lv_xml_register_subject(NULL, "s1", &s1);
const char * label2_attrs[] = { const char * label2_attrs[] = {
"bind_text", "s1", "bind_text", "s1",
"bind_text-fmt", "We have %d users", "bind_text-fmt", "We have %d users",
@@ -45,6 +46,20 @@ void test_xml_label_with_attrs(void)
lv_xml_create(scr, "lv_label", label2_attrs); lv_xml_create(scr, "lv_label", label2_attrs);
static lv_subject_t s2;
lv_subject_init_float(&s2, 12.3f);
lv_xml_register_subject(NULL, "s2", &s2);
const char * label3_attrs[] = {
"bind_text", "s2",
"bind_text-fmt", "We have measured: %0.3f mW",
"y", "30",
"x", "5",
NULL, NULL,
};
lv_xml_create(scr, "lv_label", label3_attrs);
TEST_ASSERT_EQUAL_SCREENSHOT("xml/lv_label.png"); TEST_ASSERT_EQUAL_SCREENSHOT("xml/lv_label.png");
} }