1 /**
2 * @file lv_observer.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9
10 #include "lv_observer_private.h"
11 #if LV_USE_OBSERVER
12
13 #include "../../lvgl.h"
14 #include "../../core/lv_obj_private.h"
15 #include "../../misc/lv_event_private.h"
16
17 /*********************
18 * DEFINES
19 *********************/
20
21 /**********************
22 * TYPEDEFS
23 **********************/
24 typedef struct {
25 uint32_t flag;
26 lv_subject_value_t value;
27 uint32_t inv : 1;
28 } flag_and_cond_t;
29
30 /**********************
31 * STATIC PROTOTYPES
32 **********************/
33 static void unsubscribe_on_delete_cb(lv_event_t * e);
34 static void group_notify_cb(lv_observer_t * observer, lv_subject_t * subject);
35 static lv_observer_t * bind_to_bitfield(lv_subject_t * subject, lv_obj_t * obj, lv_observer_cb_t cb, uint32_t flag,
36 int32_t ref_value, bool inv);
37 static void obj_flag_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
38 static void obj_state_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
39 static void obj_value_changed_event_cb(lv_event_t * e);
40
41 #if LV_USE_LABEL
42 static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
43 #endif
44
45 #if LV_USE_ARC
46 static void arc_value_changed_event_cb(lv_event_t * e);
47 static void arc_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
48 #endif
49
50 #if LV_USE_SLIDER
51 static void slider_value_changed_event_cb(lv_event_t * e);
52 static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
53 #endif
54
55 #if LV_USE_ROLLER
56 static void roller_value_changed_event_cb(lv_event_t * e);
57 static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
58 #endif
59
60 #if LV_USE_DROPDOWN
61 static void dropdown_value_changed_event_cb(lv_event_t * e);
62 static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
63 #endif
64
65 /**********************
66 * STATIC VARIABLES
67 **********************/
68
69 /**********************
70 * MACROS
71 **********************/
72
73 /**********************
74 * GLOBAL FUNCTIONS
75 **********************/
76
lv_subject_init_int(lv_subject_t * subject,int32_t value)77 void lv_subject_init_int(lv_subject_t * subject, int32_t value)
78 {
79 lv_memzero(subject, sizeof(lv_subject_t));
80 subject->type = LV_SUBJECT_TYPE_INT;
81 subject->value.num = value;
82 subject->prev_value.num = value;
83 lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
84 }
85
lv_subject_set_int(lv_subject_t * subject,int32_t value)86 void lv_subject_set_int(lv_subject_t * subject, int32_t value)
87 {
88 if(subject->type != LV_SUBJECT_TYPE_INT) {
89 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT");
90 return;
91 }
92
93 subject->prev_value.num = subject->value.num;
94 subject->value.num = value;
95 lv_subject_notify(subject);
96 }
97
lv_subject_get_int(lv_subject_t * subject)98 int32_t lv_subject_get_int(lv_subject_t * subject)
99 {
100 if(subject->type != LV_SUBJECT_TYPE_INT) {
101 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT");
102 return 0;
103 }
104
105 return subject->value.num;
106 }
107
lv_subject_get_previous_int(lv_subject_t * subject)108 int32_t lv_subject_get_previous_int(lv_subject_t * subject)
109 {
110 if(subject->type != LV_SUBJECT_TYPE_INT) {
111 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT");
112 return 0;
113 }
114
115 return subject->prev_value.num;
116 }
117
lv_subject_init_string(lv_subject_t * subject,char * buf,char * prev_buf,size_t size,const char * value)118 void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value)
119 {
120 lv_memzero(subject, sizeof(lv_subject_t));
121 lv_strlcpy(buf, value, size);
122 if(prev_buf) lv_strlcpy(prev_buf, value, size);
123
124 subject->type = LV_SUBJECT_TYPE_STRING;
125 subject->size = size;
126 subject->value.pointer = buf;
127 subject->prev_value.pointer = prev_buf;
128
129 lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
130 }
131
lv_subject_copy_string(lv_subject_t * subject,const char * buf)132 void lv_subject_copy_string(lv_subject_t * subject, const char * buf)
133 {
134 if(subject->type != LV_SUBJECT_TYPE_STRING) {
135 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_STRING");
136 return;
137 }
138
139 if(subject->size < 1) return;
140 if(subject->prev_value.pointer) {
141 lv_strlcpy((char *)subject->prev_value.pointer, subject->value.pointer, subject->size);
142 }
143
144 lv_strlcpy((char *)subject->value.pointer, buf, subject->size);
145
146 lv_subject_notify(subject);
147
148 }
149
lv_subject_snprintf(lv_subject_t * subject,const char * format,...)150 void lv_subject_snprintf(lv_subject_t * subject, const char * format, ...)
151 {
152 if(subject->type != LV_SUBJECT_TYPE_STRING) {
153 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_STRING");
154 return;
155 }
156
157 if(subject->size < 1) return;
158
159 if(subject->prev_value.pointer) {
160 lv_strlcpy((char *)subject->prev_value.pointer, subject->value.pointer, subject->size);
161 }
162
163 va_list va;
164 va_start(va, format);
165 const int ret = lv_vsnprintf((char *)subject->value.pointer, subject->size, format, va);
166 LV_UNUSED(ret);
167 va_end(va);
168
169 lv_subject_notify(subject);
170 }
171
lv_subject_get_string(lv_subject_t * subject)172 const char * lv_subject_get_string(lv_subject_t * subject)
173 {
174 if(subject->type != LV_SUBJECT_TYPE_STRING) {
175 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_STRING");
176 return "";
177 }
178
179 return subject->value.pointer;
180 }
181
lv_subject_get_previous_string(lv_subject_t * subject)182 const char * lv_subject_get_previous_string(lv_subject_t * subject)
183 {
184 if(subject->type != LV_SUBJECT_TYPE_STRING) {
185 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_STRING");
186 return NULL;
187 }
188
189 return subject->prev_value.pointer;
190 }
191
lv_subject_init_pointer(lv_subject_t * subject,void * value)192 void lv_subject_init_pointer(lv_subject_t * subject, void * value)
193 {
194 lv_memzero(subject, sizeof(lv_subject_t));
195 subject->type = LV_SUBJECT_TYPE_POINTER;
196 subject->value.pointer = value;
197 subject->prev_value.pointer = value;
198 lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
199 }
200
lv_subject_set_pointer(lv_subject_t * subject,void * ptr)201 void lv_subject_set_pointer(lv_subject_t * subject, void * ptr)
202 {
203 if(subject->type != LV_SUBJECT_TYPE_POINTER) {
204 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_POINTER");
205 return;
206 }
207
208 subject->prev_value.pointer = subject->value.pointer;
209 subject->value.pointer = ptr;
210 lv_subject_notify(subject);
211 }
212
lv_subject_get_pointer(lv_subject_t * subject)213 const void * lv_subject_get_pointer(lv_subject_t * subject)
214 {
215 if(subject->type != LV_SUBJECT_TYPE_POINTER) {
216 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_POINTER");
217 return NULL;
218 }
219
220 return subject->value.pointer;
221 }
222
lv_subject_get_previous_pointer(lv_subject_t * subject)223 const void * lv_subject_get_previous_pointer(lv_subject_t * subject)
224 {
225 if(subject->type != LV_SUBJECT_TYPE_POINTER) {
226 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_POINTER");
227 return NULL;
228 }
229
230 return subject->prev_value.pointer;
231 }
232
lv_subject_init_color(lv_subject_t * subject,lv_color_t color)233 void lv_subject_init_color(lv_subject_t * subject, lv_color_t color)
234 {
235 lv_memzero(subject, sizeof(lv_subject_t));
236 subject->type = LV_SUBJECT_TYPE_COLOR;
237 subject->value.color = color;
238 subject->prev_value.color = color;
239 lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
240 }
241
lv_subject_set_color(lv_subject_t * subject,lv_color_t color)242 void lv_subject_set_color(lv_subject_t * subject, lv_color_t color)
243 {
244 if(subject->type != LV_SUBJECT_TYPE_COLOR) {
245 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_COLOR");
246 return;
247 }
248
249 subject->prev_value.color = subject->value.color;
250 subject->value.color = color;
251 lv_subject_notify(subject);
252 }
253
lv_subject_get_color(lv_subject_t * subject)254 lv_color_t lv_subject_get_color(lv_subject_t * subject)
255 {
256 if(subject->type != LV_SUBJECT_TYPE_COLOR) {
257 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_COLOR");
258 return lv_color_black();
259 }
260
261 return subject->value.color;
262 }
263
lv_subject_get_previous_color(lv_subject_t * subject)264 lv_color_t lv_subject_get_previous_color(lv_subject_t * subject)
265 {
266 if(subject->type != LV_SUBJECT_TYPE_COLOR) {
267 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_COLOR");
268 return lv_color_black();
269 }
270
271 return subject->prev_value.color;
272 }
273
lv_subject_init_group(lv_subject_t * subject,lv_subject_t * list[],uint32_t list_len)274 void lv_subject_init_group(lv_subject_t * subject, lv_subject_t * list[], uint32_t list_len)
275 {
276 subject->type = LV_SUBJECT_TYPE_GROUP;
277 subject->size = list_len;
278 lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
279 subject->value.pointer = list;
280
281 /* bind all subjects to this subject */
282 uint32_t i;
283 for(i = 0; i < list_len; i++) {
284 /*If a subject in the group changes notify the group itself*/
285 lv_subject_add_observer(list[i], group_notify_cb, subject);
286 }
287 }
288
lv_subject_deinit(lv_subject_t * subject)289 void lv_subject_deinit(lv_subject_t * subject)
290 {
291 lv_observer_t * observer = lv_ll_get_head(&subject->subs_ll);
292 while(observer) {
293 lv_observer_t * observer_next = lv_ll_get_next(&subject->subs_ll, observer);
294
295 if(observer->for_obj) {
296 lv_obj_remove_event_cb(observer->target, unsubscribe_on_delete_cb);
297 lv_obj_remove_event_cb_with_user_data(observer->target, NULL, subject);
298 }
299
300 lv_observer_remove(observer);
301 observer = observer_next;
302 }
303
304 lv_ll_clear(&subject->subs_ll);
305 }
306
lv_subject_get_group_element(lv_subject_t * subject,int32_t index)307 lv_subject_t * lv_subject_get_group_element(lv_subject_t * subject, int32_t index)
308 {
309 if(subject->type != LV_SUBJECT_TYPE_GROUP) {
310 LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_GROUP");
311 return NULL;
312 }
313
314 if(index >= subject->size) return NULL;
315
316 return ((lv_subject_t **)(subject->value.pointer))[index];
317 }
318
lv_subject_add_observer(lv_subject_t * subject,lv_observer_cb_t cb,void * user_data)319 lv_observer_t * lv_subject_add_observer(lv_subject_t * subject, lv_observer_cb_t cb, void * user_data)
320 {
321 lv_observer_t * observer = lv_subject_add_observer_obj(subject, cb, NULL, user_data);
322 if(observer == NULL) return NULL;
323
324 observer->for_obj = 0;
325 return observer;
326 }
327
lv_subject_add_observer_obj(lv_subject_t * subject,lv_observer_cb_t cb,lv_obj_t * obj,void * user_data)328 lv_observer_t * lv_subject_add_observer_obj(lv_subject_t * subject, lv_observer_cb_t cb, lv_obj_t * obj,
329 void * user_data)
330 {
331 LV_ASSERT_NULL(subject);
332 if(subject->type == LV_SUBJECT_TYPE_INVALID) {
333 LV_LOG_WARN("Subject not initialized yet");
334 return NULL;
335 }
336 lv_observer_t * observer = lv_ll_ins_tail(&(subject->subs_ll));
337 LV_ASSERT_MALLOC(observer);
338 if(observer == NULL) return NULL;
339
340 lv_memzero(observer, sizeof(*observer));
341
342 observer->subject = subject;
343 observer->cb = cb;
344 observer->user_data = user_data;
345 observer->target = obj;
346 observer->for_obj = 1;
347 /* subscribe to delete event of the object */
348 if(obj != NULL) {
349 lv_obj_add_event_cb(obj, unsubscribe_on_delete_cb, LV_EVENT_DELETE, observer);
350 }
351
352 /* update object immediately */
353 if(observer->cb) observer->cb(observer, subject);
354
355 return observer;
356 }
357
lv_subject_add_observer_with_target(lv_subject_t * subject,lv_observer_cb_t cb,void * target,void * user_data)358 lv_observer_t * lv_subject_add_observer_with_target(lv_subject_t * subject, lv_observer_cb_t cb, void * target,
359 void * user_data)
360 {
361 LV_ASSERT_NULL(subject);
362 if(subject->type == LV_SUBJECT_TYPE_INVALID) {
363 LV_LOG_WARN("Subject not initialized yet");
364 return NULL;
365 }
366 lv_observer_t * observer = lv_ll_ins_tail(&(subject->subs_ll));
367 LV_ASSERT_MALLOC(observer);
368 if(observer == NULL) return NULL;
369
370 lv_memzero(observer, sizeof(*observer));
371
372 observer->subject = subject;
373 observer->cb = cb;
374 observer->user_data = user_data;
375 observer->target = target;
376
377 /* update object immediately */
378 if(observer->cb) observer->cb(observer, subject);
379
380 return observer;
381 }
382
383
lv_observer_remove(lv_observer_t * observer)384 void lv_observer_remove(lv_observer_t * observer)
385 {
386 LV_ASSERT_NULL(observer);
387
388 observer->subject->notify_restart_query = 1;
389
390 lv_ll_remove(&(observer->subject->subs_ll), observer);
391
392 if(observer->auto_free_user_data) {
393 lv_free(observer->user_data);
394 }
395 lv_free(observer);
396 }
397
lv_obj_remove_from_subject(lv_obj_t * obj,lv_subject_t * subject)398 void lv_obj_remove_from_subject(lv_obj_t * obj, lv_subject_t * subject)
399 {
400 int32_t i;
401 int32_t event_cnt = (int32_t)(obj->spec_attr ? lv_event_get_count(&obj->spec_attr->event_list) : 0);
402 for(i = event_cnt - 1; i >= 0; i--) {
403 lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(obj, i);
404 if(event_dsc->cb == unsubscribe_on_delete_cb) {
405 lv_observer_t * observer = event_dsc->user_data;
406 if(subject == NULL || subject == observer->subject) {
407 lv_observer_remove(observer);
408 lv_obj_remove_event(obj, i);
409 }
410 }
411 }
412 }
413
lv_observer_get_target(lv_observer_t * observer)414 void * lv_observer_get_target(lv_observer_t * observer)
415 {
416 LV_ASSERT_NULL(observer);
417
418 return observer->target;
419 }
420
lv_subject_notify(lv_subject_t * subject)421 void lv_subject_notify(lv_subject_t * subject)
422 {
423 LV_ASSERT_NULL(subject);
424
425 lv_observer_t * observer;
426 LV_LL_READ(&(subject->subs_ll), observer) {
427 observer->notified = 0;
428 }
429
430 do {
431 subject->notify_restart_query = 0;
432 LV_LL_READ(&(subject->subs_ll), observer) {
433 if(observer->cb && observer->notified == 0) {
434 observer->cb(observer, subject);
435 if(subject->notify_restart_query) break;
436 observer->notified = 1;
437 }
438 }
439 } while(subject->notify_restart_query);
440 }
441
lv_obj_bind_flag_if_eq(lv_obj_t * obj,lv_subject_t * subject,lv_obj_flag_t flag,int32_t ref_value)442 lv_observer_t * lv_obj_bind_flag_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value)
443 {
444 lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_flag_observer_cb, flag, ref_value, false);
445 return observable;
446 }
447
lv_obj_bind_flag_if_not_eq(lv_obj_t * obj,lv_subject_t * subject,lv_obj_flag_t flag,int32_t ref_value)448 lv_observer_t * lv_obj_bind_flag_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag,
449 int32_t ref_value)
450 {
451 lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_flag_observer_cb, flag, ref_value, true);
452 return observable;
453 }
454
lv_obj_bind_state_if_eq(lv_obj_t * obj,lv_subject_t * subject,lv_state_t state,int32_t ref_value)455 lv_observer_t * lv_obj_bind_state_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value)
456 {
457 lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_state_observer_cb, state, ref_value, false);
458 return observable;
459 }
460
lv_obj_bind_state_if_not_eq(lv_obj_t * obj,lv_subject_t * subject,lv_state_t state,int32_t ref_value)461 lv_observer_t * lv_obj_bind_state_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value)
462 {
463 lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_state_observer_cb, state, ref_value, true);
464 return observable;
465 }
466
lv_obj_bind_checked(lv_obj_t * obj,lv_subject_t * subject)467 lv_observer_t * lv_obj_bind_checked(lv_obj_t * obj, lv_subject_t * subject)
468 {
469 lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_state_observer_cb, LV_STATE_CHECKED, 1, false);
470 lv_obj_add_event_cb(obj, obj_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
471 return observable;
472 }
473
474 #if LV_USE_LABEL
lv_label_bind_text(lv_obj_t * obj,lv_subject_t * subject,const char * fmt)475 lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt)
476 {
477 LV_ASSERT_NULL(subject);
478 LV_ASSERT_NULL(obj);
479
480 if(fmt == NULL) {
481 if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER) {
482 LV_LOG_WARN("Incompatible subject type: %d", subject->type);
483 return NULL;
484 }
485 }
486 else {
487 if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER &&
488 subject->type != LV_SUBJECT_TYPE_INT) {
489 LV_LOG_WARN("Incompatible subject type: %d", subject->type);
490 return NULL;
491 }
492 }
493
494 lv_observer_t * observer = lv_subject_add_observer_obj(subject, label_text_observer_cb, obj, (void *)fmt);
495 return observer;
496 }
497 #endif /*LV_USE_LABEL*/
498
499 #if LV_USE_ARC
lv_arc_bind_value(lv_obj_t * obj,lv_subject_t * subject)500 lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject)
501 {
502 LV_ASSERT_NULL(subject);
503 LV_ASSERT_NULL(obj);
504
505 if(subject->type != LV_SUBJECT_TYPE_INT) {
506 LV_LOG_WARN("Incompatible subject type: %d", subject->type);
507 return NULL;
508 }
509
510 lv_obj_add_event_cb(obj, arc_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
511
512 lv_observer_t * observer = lv_subject_add_observer_obj(subject, arc_value_observer_cb, obj, NULL);
513 return observer;
514 }
515 #endif /*LV_USE_ARC*/
516
517 #if LV_USE_SLIDER
lv_slider_bind_value(lv_obj_t * obj,lv_subject_t * subject)518 lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject)
519 {
520 LV_ASSERT_NULL(subject);
521 LV_ASSERT_NULL(obj);
522
523 if(subject->type != LV_SUBJECT_TYPE_INT) {
524 LV_LOG_WARN("Incompatible subject type: %d", subject->type);
525 return NULL;
526 }
527
528 lv_obj_add_event_cb(obj, slider_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
529
530 lv_observer_t * observer = lv_subject_add_observer_obj(subject, slider_value_observer_cb, obj, NULL);
531 return observer;
532 }
533 #endif /*LV_USE_SLIDER*/
534
535 #if LV_USE_ROLLER
536
lv_roller_bind_value(lv_obj_t * obj,lv_subject_t * subject)537 lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject)
538 {
539 LV_ASSERT_NULL(subject);
540 LV_ASSERT_NULL(obj);
541
542 if(subject->type != LV_SUBJECT_TYPE_INT) {
543 LV_LOG_WARN("Incompatible subject type: %d", subject->type);
544 return NULL;
545 }
546
547 lv_obj_add_event_cb(obj, roller_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
548
549 lv_observer_t * observer = lv_subject_add_observer_obj(subject, roller_value_observer_cb, obj, NULL);
550 return observer;
551
552 }
553 #endif /*LV_USE_ROLLER*/
554
555 #if LV_USE_DROPDOWN
556
lv_dropdown_bind_value(lv_obj_t * obj,lv_subject_t * subject)557 lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject)
558 {
559 LV_ASSERT_NULL(subject);
560 LV_ASSERT_NULL(obj);
561
562 if(subject->type != LV_SUBJECT_TYPE_INT) {
563 LV_LOG_WARN("Incompatible subject type: %d", subject->type);
564 return NULL;
565 }
566
567 lv_obj_add_event_cb(obj, dropdown_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
568
569 lv_observer_t * observer = lv_subject_add_observer_obj(subject, dropdown_value_observer_cb, obj, NULL);
570 return observer;
571
572 }
573
574 #endif /*LV_USE_DROPDOWN*/
575
lv_observer_get_target_obj(lv_observer_t * observer)576 lv_obj_t * lv_observer_get_target_obj(lv_observer_t * observer)
577 {
578 return (lv_obj_t *)lv_observer_get_target(observer);
579 }
580
lv_observer_get_user_data(const lv_observer_t * observer)581 void * lv_observer_get_user_data(const lv_observer_t * observer)
582 {
583 LV_ASSERT_NULL(observer);
584
585 return observer->user_data;
586 }
587
588 /**********************
589 * STATIC FUNCTIONS
590 **********************/
591
group_notify_cb(lv_observer_t * observer,lv_subject_t * subject)592 static void group_notify_cb(lv_observer_t * observer, lv_subject_t * subject)
593 {
594 LV_UNUSED(subject);
595 lv_subject_t * subject_group = observer->user_data;
596 lv_subject_notify(subject_group);
597 }
598
unsubscribe_on_delete_cb(lv_event_t * e)599 static void unsubscribe_on_delete_cb(lv_event_t * e)
600 {
601 lv_observer_t * observer = lv_event_get_user_data(e);
602 lv_observer_remove(observer);
603 }
604
bind_to_bitfield(lv_subject_t * subject,lv_obj_t * obj,lv_observer_cb_t cb,uint32_t flag,int32_t ref_value,bool inv)605 static lv_observer_t * bind_to_bitfield(lv_subject_t * subject, lv_obj_t * obj, lv_observer_cb_t cb, uint32_t flag,
606 int32_t ref_value, bool inv)
607 {
608 LV_ASSERT_NULL(subject);
609 LV_ASSERT_NULL(obj);
610
611 if(subject->type != LV_SUBJECT_TYPE_INT) {
612 LV_LOG_WARN("Incompatible subject type: %d", subject->type);
613 return NULL;
614 }
615
616 flag_and_cond_t * p = lv_malloc(sizeof(flag_and_cond_t));
617 if(p == NULL) {
618 LV_LOG_WARN("Out of memory");
619 return NULL;
620 }
621
622 p->flag = flag;
623 p->value.num = ref_value;
624 p->inv = inv;
625
626 lv_observer_t * observable = lv_subject_add_observer_obj(subject, cb, obj, p);
627 observable->auto_free_user_data = 1;
628 return observable;
629 }
630
obj_flag_observer_cb(lv_observer_t * observer,lv_subject_t * subject)631 static void obj_flag_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
632 {
633 flag_and_cond_t * p = observer->user_data;
634
635 bool res = subject->value.num == p->value.num;
636 if(p->inv) res = !res;
637
638 if(res) {
639 lv_obj_add_flag(observer->target, p->flag);
640 }
641 else {
642 lv_obj_remove_flag(observer->target, p->flag);
643 }
644 }
645
obj_state_observer_cb(lv_observer_t * observer,lv_subject_t * subject)646 static void obj_state_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
647 {
648 flag_and_cond_t * p = observer->user_data;
649
650 bool res = subject->value.num == p->value.num;
651 if(p->inv) res = !res;
652
653 if(res) {
654 lv_obj_add_state(observer->target, p->flag);
655 }
656 else {
657 lv_obj_remove_state(observer->target, p->flag);
658 }
659 }
660
obj_value_changed_event_cb(lv_event_t * e)661 static void obj_value_changed_event_cb(lv_event_t * e)
662 {
663 lv_obj_t * obj = lv_event_get_current_target(e);
664 lv_subject_t * subject = lv_event_get_user_data(e);
665
666 lv_subject_set_int(subject, lv_obj_has_state(obj, LV_STATE_CHECKED));
667 }
668
669 #if LV_USE_LABEL
670
label_text_observer_cb(lv_observer_t * observer,lv_subject_t * subject)671 static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
672 {
673 const char * fmt = observer->user_data;
674
675 if(fmt == NULL) {
676 lv_label_set_text(observer->target, subject->value.pointer);
677 }
678 else {
679 switch(subject->type) {
680 case LV_SUBJECT_TYPE_INT:
681 lv_label_set_text_fmt(observer->target, fmt, subject->value.num);
682 break;
683 case LV_SUBJECT_TYPE_STRING:
684 case LV_SUBJECT_TYPE_POINTER:
685 lv_label_set_text_fmt(observer->target, fmt, subject->value.pointer);
686 break;
687 default:
688 break;
689 }
690 }
691 }
692
693 #endif /*LV_USE_LABEL*/
694
695 #if LV_USE_ARC
696
arc_value_changed_event_cb(lv_event_t * e)697 static void arc_value_changed_event_cb(lv_event_t * e)
698 {
699 lv_obj_t * arc = lv_event_get_current_target(e);
700 lv_subject_t * subject = lv_event_get_user_data(e);
701
702 lv_subject_set_int(subject, lv_arc_get_value(arc));
703 }
704
arc_value_observer_cb(lv_observer_t * observer,lv_subject_t * subject)705 static void arc_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
706 {
707 lv_arc_set_value(observer->target, subject->value.num);
708 }
709
710 #endif /*LV_USE_ARC*/
711
712 #if LV_USE_SLIDER
713
slider_value_changed_event_cb(lv_event_t * e)714 static void slider_value_changed_event_cb(lv_event_t * e)
715 {
716 lv_obj_t * slider = lv_event_get_current_target(e);
717 lv_subject_t * subject = lv_event_get_user_data(e);
718
719 lv_subject_set_int(subject, lv_slider_get_value(slider));
720 }
721
slider_value_observer_cb(lv_observer_t * observer,lv_subject_t * subject)722 static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
723 {
724 lv_slider_set_value(observer->target, subject->value.num, LV_ANIM_OFF);
725 }
726
727 #endif /*LV_USE_SLIDER*/
728
729 #if LV_USE_ROLLER
730
roller_value_changed_event_cb(lv_event_t * e)731 static void roller_value_changed_event_cb(lv_event_t * e)
732 {
733 lv_obj_t * roller = lv_event_get_current_target(e);
734 lv_subject_t * subject = lv_event_get_user_data(e);
735
736 lv_subject_set_int(subject, lv_roller_get_selected(roller));
737 }
738
roller_value_observer_cb(lv_observer_t * observer,lv_subject_t * subject)739 static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
740 {
741 if((int32_t)lv_roller_get_selected(observer->target) != subject->value.num) {
742 lv_roller_set_selected(observer->target, subject->value.num, LV_ANIM_OFF);
743 }
744 }
745
746 #endif /*LV_USE_ROLLER*/
747
748 #if LV_USE_DROPDOWN
749
dropdown_value_changed_event_cb(lv_event_t * e)750 static void dropdown_value_changed_event_cb(lv_event_t * e)
751 {
752 lv_obj_t * dropdown = lv_event_get_current_target(e);
753 lv_subject_t * subject = lv_event_get_user_data(e);
754
755 lv_subject_set_int(subject, lv_dropdown_get_selected(dropdown));
756 }
757
dropdown_value_observer_cb(lv_observer_t * observer,lv_subject_t * subject)758 static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
759 {
760 lv_dropdown_set_selected(observer->target, subject->value.num, LV_ANIM_OFF);
761 }
762
763 #endif /*LV_USE_DROPDOWN*/
764
765 #endif /*LV_USE_OBSERVER*/
766