refactor(observer): move bindings to the related widgets

This commit is contained in:
Gabor Kiss-Vamosi
2025-09-02 11:53:51 +02:00
parent ec0e3cfab5
commit 26fd3e7574
17 changed files with 534 additions and 497 deletions
-403
View File
@@ -55,12 +55,6 @@ 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;
int32_t step;
@@ -93,39 +87,6 @@ static void obj_value_changed_event_cb(lv_event_t * e);
static void lv_subject_notify_if_changed(lv_subject_t * subject);
#if LV_USE_LABEL
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);
#endif
#if LV_USE_SLIDER
static void slider_value_changed_event_cb(lv_event_t * e);
static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif
#if LV_USE_ROLLER
static void roller_value_changed_event_cb(lv_event_t * e);
static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif
#if LV_USE_DROPDOWN
static void dropdown_value_changed_event_cb(lv_event_t * e);
static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif
#if LV_USE_SCALE
static void scale_section_min_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
static void scale_section_max_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif
static void subject_set_string_free_user_data_event_cb(lv_event_t * e);
/**********************
@@ -759,192 +720,6 @@ lv_observer_t * lv_obj_bind_checked(lv_obj_t * obj, lv_subject_t * subject)
return observable;
}
#if LV_USE_LABEL
lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
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;
}
}
lv_observer_t * observer = lv_subject_add_observer_obj(subject, label_text_observer_cb, obj, (void *)fmt);
return observer;
}
#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)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT && subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_obj_add_event_cb(obj, arc_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
lv_observer_t * observer = lv_subject_add_observer_obj(subject, arc_value_observer_cb, obj, NULL);
return observer;
}
#endif /*LV_USE_ARC*/
#if LV_USE_SLIDER
lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT && subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_obj_add_event_cb(obj, slider_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
lv_observer_t * observer = lv_subject_add_observer_obj(subject, slider_value_observer_cb, obj, NULL);
return observer;
}
#endif /*LV_USE_SLIDER*/
#if LV_USE_ROLLER
lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_obj_add_event_cb(obj, roller_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
lv_observer_t * observer = lv_subject_add_observer_obj(subject, roller_value_observer_cb, obj, NULL);
return observer;
}
#endif /*LV_USE_ROLLER*/
#if LV_USE_DROPDOWN
lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_obj_add_event_cb(obj, dropdown_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
lv_observer_t * observer = lv_subject_add_observer_obj(subject, dropdown_value_observer_cb, obj, NULL);
return observer;
}
#endif /*LV_USE_DROPDOWN*/
#if LV_USE_SCALE
lv_observer_t * lv_scale_bind_section_min_value(lv_obj_t * obj, lv_scale_section_t * section, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_observer_t * observer = lv_subject_add_observer_obj(subject, scale_section_min_value_observer_cb, obj, section);
return observer;
}
lv_observer_t * lv_scale_bind_section_max_value(lv_obj_t * obj, lv_scale_section_t * section, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_observer_t * observer = lv_subject_add_observer_obj(subject, scale_section_max_value_observer_cb, obj, section);
return observer;
}
#endif /*LV_USE_SCALE*/
lv_obj_t * lv_observer_get_target_obj(lv_observer_t * observer)
{
@@ -1154,184 +929,6 @@ static void lv_subject_notify_if_changed(lv_subject_t * subject)
}
}
#if LV_USE_LABEL
static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
const char * fmt = observer->user_data;
if(fmt == NULL) {
lv_label_set_text(observer->target, subject->value.pointer);
}
else {
switch(subject->type) {
case LV_SUBJECT_TYPE_INT:
lv_label_set_text_fmt(observer->target, fmt, subject->value.num);
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_POINTER:
lv_label_set_text_fmt(observer->target, fmt, subject->value.pointer);
break;
default:
break;
}
}
}
#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)
{
lv_obj_t * arc = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e);
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)
{
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*/
#if LV_USE_SLIDER
static void slider_value_changed_event_cb(lv_event_t * e)
{
lv_obj_t * slider = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e);
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)
{
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*/
#if LV_USE_ROLLER
static void roller_value_changed_event_cb(lv_event_t * e)
{
lv_obj_t * roller = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e);
lv_subject_set_int(subject, lv_roller_get_selected(roller));
}
static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
if((int32_t)lv_roller_get_selected(observer->target) != subject->value.num) {
lv_roller_set_selected(observer->target, subject->value.num, LV_ANIM_OFF);
}
}
#endif /*LV_USE_ROLLER*/
#if LV_USE_DROPDOWN
static void dropdown_value_changed_event_cb(lv_event_t * e)
{
lv_obj_t * dropdown = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e);
lv_subject_set_int(subject, lv_dropdown_get_selected(dropdown));
}
static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
lv_dropdown_set_selected(observer->target, subject->value.num);
}
#endif /*LV_USE_DROPDOWN*/
#if LV_USE_SCALE
static void scale_section_min_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
lv_scale_section_t * section = observer->user_data;
lv_scale_set_section_min_value(observer->target, section, subject->value.num);
}
static void scale_section_max_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
lv_scale_section_t * section = observer->user_data;
lv_scale_set_section_max_value(observer->target, section, subject->value.num);
}
#endif /*LV_USE_SCALE*/
static void subject_set_string_free_user_data_event_cb(lv_event_t * e)
{
subject_set_string_user_data_t * user_data = lv_event_get_user_data(e);
-94
View File
@@ -530,100 +530,6 @@ lv_observer_t * lv_obj_bind_state_if_le(lv_obj_t * obj, lv_subject_t * subject,
*/
lv_observer_t * lv_obj_bind_checked(lv_obj_t * obj, lv_subject_t * subject);
#if LV_USE_LABEL
/**
* Bind an integer, string, or pointer Subject to a Label.
* @param obj pointer to Label
* @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_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt);
#endif
#if LV_USE_SPAN
/**
* Bind an integer, string, or pointer Subject to a Spangroup's Span.
* @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 `fmt == NULL` strings and pointers (`\0` terminated string) will be shown
* as text as they are, integers as %d, floats as %0.1f
*/
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.
* @param obj pointer to Arc
* @param subject pointer to Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject);
#endif
#if LV_USE_SLIDER
/**
* Bind an integer Subject to a Slider's value.
* @param obj pointer to Slider
* @param subject pointer to Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject);
#endif
#if LV_USE_ROLLER
/**
* Bind an integer Subject to a Roller's value.
* @param obj pointer to Roller
* @param subject pointer to Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject);
#endif
#if LV_USE_DROPDOWN
/**
* Bind an integer Subject to a Dropdown's value.
* @param obj pointer to Dropdown
* @param subject pointer to Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject);
#endif
#if LV_USE_SCALE
/**
* Bind an integer subject to a scales section minimum value
* @param obj pointer to a Scale
* @param section pointer to a Scale section
* @param subject pointer to a Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_scale_bind_section_min_value(lv_obj_t * obj, lv_scale_section_t * section, lv_subject_t * subject);
/**
* Bind an integer subject to a scales section maximum value
* @param obj pointer to an Scale
* @param section pointer to a Scale section
* @param subject pointer to a Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_scale_bind_section_max_value(lv_obj_t * obj, lv_scale_section_t * section, lv_subject_t * subject);
#endif
/**********************
* MACROS
+56
View File
@@ -18,6 +18,7 @@
#include "../../misc/lv_assert.h"
#include "../../misc/lv_math.h"
#include "../../draw/lv_draw_arc.h"
#include "../../others/observer/lv_observer_private.h"
/*********************
* DEFINES
@@ -50,6 +51,10 @@ static void value_update(lv_obj_t * arc);
static int32_t knob_get_extra_size(lv_obj_t * obj);
static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const lv_value_precise_t angle,
const lv_value_precise_t tolerance_deg);
#if LV_USE_OBSERVER
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);
#endif /*LV_USE_OBSERVER*/
/**********************
* STATIC VARIABLES
@@ -367,6 +372,25 @@ int32_t lv_arc_get_knob_offset(const lv_obj_t * obj)
* Other functions
*====================*/
#if LV_USE_OBSERVER
lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT && subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_obj_add_event_cb(obj, arc_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
lv_observer_t * observer = lv_subject_add_observer_obj(subject, arc_value_observer_cb, obj, NULL);
return observer;
}
#endif /*LV_USE_OBSERVER*/
void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, int32_t r_offset)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
@@ -1025,4 +1049,36 @@ static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const lv_value_precise
return false;
}
#if LV_USE_OBSERVER
static void arc_value_changed_event_cb(lv_event_t * e)
{
lv_obj_t * arc = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e);
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)
{
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_OBSERVER*/
#endif
+12
View File
@@ -18,6 +18,7 @@ extern "C" {
#if LV_USE_ARC != 0
#include "../../core/lv_obj.h"
#include "../../others/observer/lv_observer.h"
/*********************
* DEFINES
@@ -232,6 +233,17 @@ int32_t lv_arc_get_knob_offset(const lv_obj_t * obj);
* Other functions
*====================*/
#if LV_USE_OBSERVER
/**
* Bind an integer subject to an Arc's value.
* @param obj pointer to Arc
* @param subject pointer to Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject);
#endif
/**
* Align an object to the current position of the arc (knob)
* @param obj pointer to an arc object
+1
View File
@@ -20,6 +20,7 @@ extern "C" {
#include "../../core/lv_obj.h"
#include "../../misc/lv_anim.h"
#include "../label/lv_label.h"
#include "../../others/observer/lv_observer.h"
/*********************
* DEFINES
+45
View File
@@ -22,6 +22,7 @@
#include "../../misc/lv_math.h"
#include "../../misc/lv_text_ap.h"
#include "../../misc/lv_text_private.h"
#include "../../others/observer/lv_observer_private.h"
#include "../../stdlib/lv_string.h"
/*********************
@@ -59,6 +60,11 @@ static uint32_t get_id_on_point(lv_obj_t * dropdown_obj, int32_t y);
static void position_to_selected(lv_obj_t * dropdown_obj, lv_anim_enable_t anim_en);
static lv_obj_t * get_label(const lv_obj_t * obj);
#if LV_USE_OBSERVER
static void dropdown_value_changed_event_cb(lv_event_t * e);
static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif /*LV_USE_OBSERVER*/
/**********************
* STATIC VARIABLES
**********************/
@@ -636,6 +642,27 @@ bool lv_dropdown_is_open(lv_obj_t * obj)
return lv_obj_has_flag(dropdown->list, LV_OBJ_FLAG_HIDDEN) ? false : true;
}
#if LV_USE_OBSERVER
lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_obj_add_event_cb(obj, dropdown_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
lv_observer_t * observer = lv_subject_add_observer_obj(subject, dropdown_value_observer_cb, obj, NULL);
return observer;
}
#endif /*LV_USE_OBSERVER*/
/**********************
* STATIC FUNCTIONS
**********************/
@@ -1257,4 +1284,22 @@ static lv_obj_t * get_label(const lv_obj_t * obj)
return lv_obj_get_child(dropdown->list, 0);
}
#if LV_USE_OBSERVER
static void dropdown_value_changed_event_cb(lv_event_t * e)
{
lv_obj_t * dropdown = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e);
lv_subject_set_int(subject, lv_dropdown_get_selected(dropdown));
}
static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
lv_dropdown_set_selected(observer->target, subject->value.num);
}
#endif /*LV_USE_OBSERVER*/
#endif
+11
View File
@@ -233,6 +233,17 @@ void lv_dropdown_close(lv_obj_t * obj);
*/
bool lv_dropdown_is_open(lv_obj_t * obj);
#if LV_USE_OBSERVER
/**
* Bind an integer Subject to a Dropdown's value.
* @param obj pointer to Dropdown
* @param subject pointer to Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject);
#endif
/**********************
* MACROS
**********************/
+73
View File
@@ -24,6 +24,7 @@
#include "../../misc/lv_text_private.h"
#include "../../stdlib/lv_sprintf.h"
#include "../../stdlib/lv_string.h"
#include "../../others/observer/lv_observer_private.h"
/*********************
* DEFINES
@@ -59,6 +60,10 @@ static lv_text_flag_t get_label_flags(lv_label_t * label);
static void calculate_x_coordinate(int32_t * x, const lv_text_align_t align, const char * txt,
uint32_t length, const lv_font_t * font, lv_area_t * txt_coords, lv_text_attributes_t * attributes);
#if LV_USE_OBSERVER
static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif
/**********************
* STATIC VARIABLES
**********************/
@@ -664,6 +669,40 @@ bool lv_label_get_recolor(const lv_obj_t * obj)
* Other functions
*====================*/
#if LV_USE_OBSERVER
lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
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;
}
}
lv_observer_t * observer = lv_subject_add_observer_obj(subject, label_text_observer_cb, obj, (void *)fmt);
return observer;
}
#endif /*LV_USE_OBSERVER*/
void lv_label_ins_text(lv_obj_t * obj, uint32_t pos, const char * txt)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
@@ -710,6 +749,8 @@ void lv_label_cut_text(lv_obj_t * obj, uint32_t pos, uint32_t cnt)
lv_label_refr_text(obj);
}
/**********************
* STATIC FUNCTIONS
**********************/
@@ -1331,4 +1372,36 @@ static void calculate_x_coordinate(int32_t * x, const lv_text_align_t align, con
}
}
#if LV_USE_OBSERVER
static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
const char * fmt = observer->user_data;
if(fmt == NULL) {
lv_label_set_text(observer->target, subject->value.pointer);
}
else {
switch(subject->type) {
case LV_SUBJECT_TYPE_INT:
lv_label_set_text_fmt(observer->target, fmt, subject->value.num);
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_POINTER:
lv_label_set_text_fmt(observer->target, fmt, subject->value.pointer);
break;
default:
break;
}
}
}
#endif /*LV_USE_LABEL*/
#endif
+19
View File
@@ -23,6 +23,7 @@ extern "C" {
#include "../../font/lv_symbol_def.h"
#include "../../misc/lv_text.h"
#include "../../draw/lv_draw.h"
#include "../../others/observer/lv_observer.h"
/*********************
* DEFINES
@@ -227,6 +228,22 @@ bool lv_label_get_recolor(const lv_obj_t * obj);
* Other functions
*====================*/
#if LV_USE_OBSERVER
/**
* Bind an integer, string, or pointer Subject to a Label.
* @param obj pointer to Label
* @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_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt);
#endif
/**
* Insert a text to a label. The label text cannot be static.
* @param obj pointer to a label object
@@ -245,6 +262,8 @@ void lv_label_ins_text(lv_obj_t * obj, uint32_t pos, const char * txt);
*/
void lv_label_cut_text(lv_obj_t * obj, uint32_t pos, uint32_t cnt);
/**********************
* MACROS
**********************/
+45
View File
@@ -22,6 +22,7 @@
#include "../../indev/lv_indev_scroll.h"
#include "../../indev/lv_indev_private.h"
#include "../../stdlib/lv_string.h"
#include "../../others/observer/lv_observer_private.h"
/*********************
* DEFINES
@@ -52,6 +53,11 @@ static void scroll_anim_completed_cb(lv_anim_t * a);
static void set_y_anim(void * obj, int32_t v);
static void transform_vect_recursive(lv_obj_t * roller, lv_point_t * vect);
#if LV_USE_OBSERVER
static void roller_value_changed_event_cb(lv_event_t * e);
static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif /*LV_USE_OBSERVER*/
/**********************
* STATIC VARIABLES
**********************/
@@ -328,6 +334,25 @@ uint32_t lv_roller_get_option_count(const lv_obj_t * obj)
}
}
#if LV_USE_OBSERVER
lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_obj_add_event_cb(obj, roller_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
lv_observer_t * observer = lv_subject_add_observer_obj(subject, roller_value_observer_cb, obj, NULL);
return observer;
}
#endif /*LV_USE_OBSERVER*/
/**********************
* STATIC FUNCTIONS
**********************/
@@ -915,4 +940,24 @@ static void transform_vect_recursive(lv_obj_t * roller, lv_point_t * vect)
lv_point_transform(vect, -angle, scale_x, scale_y, &pivot, false);
}
#if LV_USE_OBSERVER
static void roller_value_changed_event_cb(lv_event_t * e)
{
lv_obj_t * roller = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e);
lv_subject_set_int(subject, lv_roller_get_selected(roller));
}
static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
if((int32_t)lv_roller_get_selected(observer->target) != subject->value.num) {
lv_roller_set_selected(observer->target, subject->value.num, LV_ANIM_OFF);
}
}
#endif /*LV_USE_OBSERVER*/
#endif
+11
View File
@@ -129,6 +129,17 @@ const char * lv_roller_get_options(const lv_obj_t * obj);
*/
uint32_t lv_roller_get_option_count(const lv_obj_t * obj);
#if LV_USE_OBSERVER
/**
* Bind an integer Subject to a Roller's value.
* @param obj pointer to Roller
* @param subject pointer to Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject);
#endif
/**********************
* MACROS
**********************/
+57
View File
@@ -15,6 +15,7 @@
#include "../../misc/lv_assert.h"
#include "../../misc/lv_math.h"
#include "../../misc/lv_text_private.h"
#include "../../others/observer/lv_observer_private.h"
#include "../../draw/lv_draw_arc.h"
/*********************
@@ -70,6 +71,11 @@ static void scale_free_line_needle_points_cb(lv_event_t * e);
static bool scale_is_major_tick(lv_scale_t * scale, uint32_t tick_idx);
#if LV_USE_OBSERVER
static void scale_section_min_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
static void scale_section_max_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif /*LV_USE_OBSERVER*/
/**********************
* STATIC VARIABLES
**********************/
@@ -517,6 +523,40 @@ int32_t lv_scale_get_range_max_value(lv_obj_t * obj)
* Other functions
*====================*/
#if LV_USE_OBSERVER
lv_observer_t * lv_scale_bind_section_min_value(lv_obj_t * obj, lv_scale_section_t * section, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_observer_t * observer = lv_subject_add_observer_obj(subject, scale_section_min_value_observer_cb, obj, section);
return observer;
}
lv_observer_t * lv_scale_bind_section_max_value(lv_obj_t * obj, lv_scale_section_t * section, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_observer_t * observer = lv_subject_add_observer_obj(subject, scale_section_max_value_observer_cb, obj, section);
return observer;
}
#endif /*LV_USE_OBSERVER*/
/**********************
* STATIC FUNCTIONS
**********************/
@@ -1719,4 +1759,21 @@ static bool scale_is_major_tick(lv_scale_t * scale, uint32_t tick_idx)
return scale->major_tick_every != 0 && tick_idx % scale->major_tick_every == 0;
}
#if LV_USE_OBSERVER
static void scale_section_min_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
lv_scale_section_t * section = observer->user_data;
lv_scale_set_section_min_value(observer->target, section, subject->value.num);
}
static void scale_section_max_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
{
lv_scale_section_t * section = observer->user_data;
lv_scale_set_section_max_value(observer->target, section, subject->value.num);
}
#endif /*LV_USE_OBSERVER*/
#endif
+27
View File
@@ -20,6 +20,7 @@ extern "C" {
#include "../../core/lv_obj.h"
#include "../line/lv_line.h"
#include "../image/lv_image.h"
#include "../../others/observer/lv_observer.h"
/*********************
* DEFINES
@@ -344,6 +345,32 @@ int32_t lv_scale_get_range_min_value(lv_obj_t * obj);
*/
int32_t lv_scale_get_range_max_value(lv_obj_t * obj);
/*=====================
* Other functions
*====================*/
#if LV_USE_OBSERVER
/**
* Bind an integer subject to a scales section minimum value
* @param obj pointer to a Scale
* @param section pointer to a Scale section
* @param subject pointer to a Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_scale_bind_section_min_value(lv_obj_t * obj, lv_scale_section_t * section, lv_subject_t * subject);
/**
* Bind an integer subject to a scales section maximum value
* @param obj pointer to an Scale
* @param section pointer to a Scale section
* @param subject pointer to a Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_scale_bind_section_max_value(lv_obj_t * obj, lv_scale_section_t * section, lv_subject_t * subject);
#endif
/**********************
* MACROS
**********************/
+58
View File
@@ -22,6 +22,7 @@
#include "../../stdlib/lv_string.h"
#include "../../misc/lv_math.h"
#include "../image/lv_image.h"
#include "../../others/observer/lv_observer_private.h"
/*********************
* DEFINES
@@ -46,6 +47,11 @@ static bool is_slider_horizontal(lv_obj_t * obj);
static void drag_start(lv_obj_t * obj);
static void update_knob_pos(lv_obj_t * obj, bool check_drag);
#if LV_USE_OBSERVER
static void slider_value_changed_event_cb(lv_event_t * e);
static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif /*LV_USE_OBSERVER*/
/**********************
* STATIC VARIABLES
**********************/
@@ -216,6 +222,25 @@ bool lv_slider_is_symmetrical(lv_obj_t * obj)
return lv_bar_is_symmetrical(obj);
}
#if LV_USE_OBSERVER
lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject)
{
LV_ASSERT_NULL(subject);
LV_ASSERT_NULL(obj);
if(subject->type != LV_SUBJECT_TYPE_INT && subject->type != LV_SUBJECT_TYPE_FLOAT) {
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
return NULL;
}
lv_obj_add_event_cb(obj, slider_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
lv_observer_t * observer = lv_subject_add_observer_obj(subject, slider_value_observer_cb, obj, NULL);
return observer;
}
#endif /*LV_USE_OBSERVER*/
/**********************
* STATIC FUNCTIONS
**********************/
@@ -637,4 +662,37 @@ static void update_knob_pos(lv_obj_t * obj, bool check_drag)
}
}
#if LV_USE_OBSERVER
static void slider_value_changed_event_cb(lv_event_t * e)
{
lv_obj_t * slider = lv_event_get_current_target(e);
lv_subject_t * subject = lv_event_get_user_data(e);
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)
{
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_OBSERVER*/
#endif
+11
View File
@@ -183,6 +183,17 @@ lv_slider_orientation_t lv_slider_get_orientation(lv_obj_t * slider);
*/
bool lv_slider_is_symmetrical(lv_obj_t * obj);
#if LV_USE_OBSERVER
/**
* Bind an integer Subject to a Slider's value.
* @param obj pointer to Slider
* @param subject pointer to Subject
* @return pointer to newly-created Observer
*/
lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject);
#endif
/**********************
* MACROS
**********************/
+89
View File
@@ -16,6 +16,7 @@
#include "../../misc/lv_assert.h"
#include "../../misc/lv_text_private.h"
#include "../../misc/lv_bidi_private.h"
#include "../../others/observer/lv_observer_private.h"
#include "../../misc/lv_text_ap.h"
#include "../../core/lv_global.h"
@@ -43,6 +44,11 @@ struct _snippet_stack {
uint32_t index;
};
typedef struct {
lv_subject_t * subject;
void * element; /**< span of a span group*/
const char * fmt;
} bind_element_string_t;
/**********************
* STATIC PROTOTYPES
**********************/
@@ -71,6 +77,9 @@ static int32_t convert_indent_pct(lv_obj_t * spans, int32_t width);
static lv_span_coords_t make_span_coords(const lv_span_t * prev_span, const lv_span_t * curr_span, int32_t width,
lv_area_t padding, int32_t indent);
#if LV_USE_OBSERVER
static void span_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
#endif
/**********************
* STATIC VARIABLES
@@ -729,6 +738,54 @@ void lv_spangroup_refresh(lv_obj_t * obj)
lv_obj_refresh_self_size(obj);
}
#if LV_USE_OBSERVER
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_OBSERVER*/
/**********************
* STATIC FUNCTIONS
**********************/
@@ -1398,4 +1455,36 @@ static lv_span_coords_t make_span_coords(const lv_span_t * prev_span, const lv_s
return coords;
}
#if LV_USE_OBSERVER
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_OBSERVER*/
#endif
+19
View File
@@ -15,6 +15,7 @@ extern "C" {
*********************/
#include "../../lv_conf_internal.h"
#include "../../core/lv_obj.h"
#include "../../others/observer/lv_observer.h"
#if LV_USE_SPAN != 0
@@ -334,6 +335,24 @@ lv_span_t * lv_spangroup_get_span_by_point(lv_obj_t * obj, const lv_point_t * po
*/
void lv_spangroup_refresh(lv_obj_t * obj);
#if LV_USE_OBSERVER
/**
* Bind an integer, string, or pointer Subject to a Spangroup's Span.
* @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 `fmt == NULL` strings and pointers (`\0` terminated string) will be shown
* as text as they are, integers as %d, floats as %0.1f
*/
lv_observer_t * lv_spangroup_bind_span_text(lv_obj_t * obj, lv_span_t * span, lv_subject_t * subject, const char * fmt);
#endif
/**********************
* MACROS
**********************/