1 /**
2  * @file lv_observer.h
3  *
4  */
5 
6 #ifndef LV_OBSERVER_H
7 #define LV_OBSERVER_H
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 /*********************
14  *      INCLUDES
15  *********************/
16 
17 #include "../../core/lv_obj.h"
18 #if LV_USE_OBSERVER
19 
20 /*********************
21  *      DEFINES
22  *********************/
23 
24 /**********************
25  *      TYPEDEFS
26  **********************/
27 
28 /**
29  * Values for lv_submect_t's `type` field.
30  */
31 typedef enum {
32     LV_SUBJECT_TYPE_INVALID =   0,   /**< indicates subject not initialized yet*/
33     LV_SUBJECT_TYPE_NONE =      1,   /**< a null value like None or NILt*/
34     LV_SUBJECT_TYPE_INT =       2,   /**< an int32_t*/
35     LV_SUBJECT_TYPE_POINTER =   3,   /**< a void pointer*/
36     LV_SUBJECT_TYPE_COLOR   =   4,   /**< an lv_color_t*/
37     LV_SUBJECT_TYPE_GROUP  =    5,   /**< an array of subjects*/
38     LV_SUBJECT_TYPE_STRING  =   6,   /**< a char pointer*/
39 } lv_subject_type_t;
40 
41 /**
42  * A common type to handle all the various observable types in the same way
43  */
44 typedef union {
45     int32_t num; /**< Integer number (opacity, enums, booleans or "normal" numbers)*/
46     const void * pointer; /**< Constant pointer  (string buffer, format string, font, cone text, etc)*/
47     lv_color_t color; /**< Color */
48 } lv_subject_value_t;
49 
50 /**
51  * The subject (an observable value)
52  */
53 typedef struct {
54     lv_ll_t subs_ll;                    /**< Subscribers*/
55     uint32_t type   : 4;
56     uint32_t size   : 28;               /**< Might be used to store a size related to `type`*/
57     lv_subject_value_t value;           /**< Actual value*/
58     lv_subject_value_t prev_value;      /**< Previous value*/
59     uint32_t notify_restart_query : 1; /**< If an observer deleted start notifying from the beginning. */
60     void * user_data;                   /**< Additional parameter, can be used freely by the user*/
61 } lv_subject_t;
62 
63 /**
64   * Callback called when the observed value changes
65   * @param observer     pointer to the observer of the callback
66   * @param subject      pointer to the subject of the observer
67   */
68 typedef void (*lv_observer_cb_t)(lv_observer_t * observer, lv_subject_t * subject);
69 
70 /**********************
71  * GLOBAL PROTOTYPES
72  **********************/
73 
74 /**
75  * Initialize an integer type subject
76  * @param subject   pointer to the subject
77  * @param value     initial value
78  */
79 void lv_subject_init_int(lv_subject_t * subject, int32_t value);
80 
81 /**
82  * Set the value of an integer subject. It will notify all the observers as well.
83  * @param subject   pointer to the subject
84  * @param value     the new value
85  */
86 void lv_subject_set_int(lv_subject_t * subject, int32_t value);
87 
88 /**
89  * Get the current value of an integer subject
90  * @param subject   pointer to the subject
91  * @return          the current value
92  */
93 int32_t lv_subject_get_int(lv_subject_t * subject);
94 
95 /**
96  * Get the previous value of an integer subject
97  * @param subject   pointer to the subject
98  * @return          the current value
99  */
100 int32_t lv_subject_get_previous_int(lv_subject_t * subject);
101 
102 /**
103  * Initialize a string type subject
104  * @param subject   pointer to the subject
105  * @param buf       pointer to a buffer to store the string
106  * @param prev_buf  pointer to a buffer to store the previous string, can be NULL if not used
107  * @param size      size of the buffer
108  * @param value     initial value as a string, e.g. "hello"
109  * @note            the string subject stores the whole string, not only a pointer
110  */
111 void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value);
112 
113 /**
114  * Copy a string to a subject. It will notify all the observers as well.
115  * @param subject   pointer to the subject
116  * @param buf       the new string
117  */
118 void lv_subject_copy_string(lv_subject_t * subject, const char * buf);
119 
120 /**
121  * Print a formatted string to a subject. It will notify all the observers as well.
122  * @param subject   pointer to the subject
123  * @param format    the format string
124  */
125 void lv_subject_snprintf(lv_subject_t * subject, const char * format, ...) LV_FORMAT_ATTRIBUTE(2, 3);
126 
127 /**
128  * Get the current value of an string subject
129  * @param subject   pointer to the subject
130  * @return          pointer to the buffer containing the current value
131  */
132 const char * lv_subject_get_string(lv_subject_t * subject);
133 
134 /**
135  * Get the previous value of an string subject
136  * @param subject   pointer to the subject
137  * @return          pointer to the buffer containing the current value
138  * @note            NULL will be returned if NULL was passed in `lv_subject_init_string()`
139  *                  as `prev_buf`
140  */
141 const char * lv_subject_get_previous_string(lv_subject_t * subject);
142 
143 /**
144  * Initialize an pointer type subject
145  * @param subject   pointer to the subject
146  * @param value     initial value
147  */
148 void lv_subject_init_pointer(lv_subject_t * subject, void * value);
149 
150 /**
151  * Set the value of a pointer subject. It will notify all the observers as well.
152  * @param subject   pointer to the subject
153  * @param ptr       new value
154  */
155 void lv_subject_set_pointer(lv_subject_t * subject, void * ptr);
156 
157 /**
158  * Get the current value of a pointer subject
159  * @param subject   pointer to the subject
160  * @return          current value
161  */
162 const void * lv_subject_get_pointer(lv_subject_t * subject);
163 
164 /**
165  * Get the previous value of a pointer subject
166  * @param subject   pointer to the subject
167  * @return          current value
168  */
169 const void * lv_subject_get_previous_pointer(lv_subject_t * subject);
170 
171 /**
172  * Initialize an color type subject
173  * @param subject   pointer to the subject
174  * @param color     initial value
175  */
176 void lv_subject_init_color(lv_subject_t * subject, lv_color_t color);
177 
178 /**
179  * Set the value of a color subject. It will notify all the observers as well.
180  * @param subject   pointer to the subject
181  * @param color     new value
182  */
183 void lv_subject_set_color(lv_subject_t * subject, lv_color_t color);
184 
185 /**
186  * Get the current value of a color subject
187  * @param subject   pointer to the subject
188  * @return          current value
189  */
190 lv_color_t lv_subject_get_color(lv_subject_t * subject);
191 
192 /**
193  * Get the previous value of a color subject
194  * @param subject   pointer to the subject
195  * @return          current value
196  */
197 lv_color_t lv_subject_get_previous_color(lv_subject_t * subject);
198 
199 /**
200  * Initialize a subject group
201  * @param subject   pointer to the subject
202  * @param list      list of other subject addresses, any of these changes `subject` will be notified
203  * @param list_len  number of elements in `list`
204  */
205 void lv_subject_init_group(lv_subject_t * subject, lv_subject_t * list[], uint32_t list_len);
206 
207 /**
208  * Remove all the observers from a subject and free all allocated memories in it
209  * @param subject   pointer to the subject
210  * @note            objects added with `lv_subject_add_observer_obj` should be already deleted or
211  *                  removed manually.
212  */
213 void lv_subject_deinit(lv_subject_t * subject);
214 
215 /**
216  * Get an element from the subject group's list
217  * @param subject   pointer to the subject
218  * @param index     index of the element to get
219  * @return          pointer a subject from the list, or NULL if the index is out of bounds
220  */
221 lv_subject_t * lv_subject_get_group_element(lv_subject_t * subject, int32_t index);
222 
223 /**
224  * Add an observer to a subject. When the subject changes `observer_cb` will be called.
225  * @param subject       pointer to the subject
226  * @param observer_cb   callback to call
227  * @param user_data     optional user data
228  * @return              pointer to the created observer
229  */
230 lv_observer_t * lv_subject_add_observer(lv_subject_t * subject, lv_observer_cb_t observer_cb, void * user_data);
231 
232 /**
233  * Add an observer to a subject for an object.
234  * When the object is deleted, it will be removed from the subject automatically.
235  * @param subject       pointer to the subject
236  * @param observer_cb   callback to call
237  * @param obj           pointer to an object
238  * @param user_data     optional user data
239  * @return              pointer to the created observer
240  */
241 lv_observer_t * lv_subject_add_observer_obj(lv_subject_t * subject, lv_observer_cb_t observer_cb, lv_obj_t * obj,
242                                             void * user_data);
243 
244 /**
245  * Add an observer to a subject and also save a target.
246  * @param subject       pointer to the subject
247  * @param observer_cb   callback to call
248  * @param target        pointer to any data
249  * @param user_data     optional user data
250  * @return              pointer to the created observer
251  */
252 lv_observer_t * lv_subject_add_observer_with_target(lv_subject_t * subject, lv_observer_cb_t observer_cb,
253                                                     void * target, void * user_data);
254 
255 /**
256  * Remove an observer from its subject
257  * @param observer      pointer to an observer
258  */
259 void lv_observer_remove(lv_observer_t * observer);
260 
261 /**
262  * Remove the observers of an object from a subject or all subjects
263  * @param obj       the object whose observers should be removed
264  * @param subject   the subject to remove the object from, or `NULL` to remove from all subjects
265  * @note This function can be used e.g. when an object's subject(s) needs to be replaced by other subject(s)
266  */
267 void lv_obj_remove_from_subject(lv_obj_t * obj, lv_subject_t * subject);
268 
269 /**
270  * Get the target of an observer
271  * @param observer      pointer to an observer
272  * @return              pointer to the saved target
273  */
274 void * lv_observer_get_target(lv_observer_t * observer);
275 
276 /**
277  * Get the target object of the observer.
278  * It's the same as `lv_observer_get_target` and added only
279  * for semantic reasons
280  * @param observer      pointer to an observer
281  * @return              pointer to the saved object target
282  */
283 lv_obj_t * lv_observer_get_target_obj(lv_observer_t * observer);
284 
285 /**
286  * Get the user data of the observer.
287  * @param observer      pointer to an observer
288  * @return              void pointer to the saved user data
289 */
290 void * lv_observer_get_user_data(const lv_observer_t * observer);
291 
292 /**
293  * Notify all observers of subject
294  * @param subject       pointer to a subject
295  */
296 void lv_subject_notify(lv_subject_t * subject);
297 
298 /**
299  * Set an object flag if an integer subject's value is equal to a reference value, clear the flag otherwise
300  * @param obj           pointer to an object
301  * @param subject       pointer to a subject
302  * @param flag          flag to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
303  * @param ref_value     reference value to compare the subject's value with
304  * @return              pointer to the created observer
305  */
306 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);
307 
308 /**
309  * Set an object flag if an integer subject's value is not equal to a reference value, clear the flag otherwise
310  * @param obj           pointer to an object
311  * @param subject       pointer to a subject
312  * @param flag          flag to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
313  * @param ref_value     reference value to compare the subject's value with
314  * @return              pointer to the created observer
315  */
316 lv_observer_t * lv_obj_bind_flag_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag,
317                                            int32_t ref_value);
318 
319 /**
320  * Set an object state if an integer subject's value is equal to a reference value, clear the flag otherwise
321  * @param obj           pointer to an object
322  * @param subject       pointer to a subject
323  * @param state         state to set or clear (e.g. `LV_STATE_CHECKED`)
324  * @param ref_value     reference value to compare the subject's value with
325  * @return              pointer to the created observer
326  */
327 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);
328 
329 /**
330  * Set an object state if an integer subject's value is not equal to a reference value, clear the flag otherwise
331  * @param obj           pointer to an object
332  * @param subject       pointer to a subject
333  * @param state         state to set or clear (e.g. `LV_STATE_CHECKED`)
334  * @param ref_value     reference value to compare the subject's value with
335  * @return              pointer to the created observer
336  */
337 lv_observer_t * lv_obj_bind_state_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state,
338                                             int32_t ref_value);
339 
340 /**
341  * Set an integer subject to 1 when an object is checked and set it 0 when unchecked.
342  * @param obj       pointer to an object
343  * @param subject   pointer to a subject
344  * @return          pointer to the created observer
345  * @note            Ensure the object's `LV_OBJ_FLAG_CHECKABLE` flag is set
346  */
347 lv_observer_t * lv_obj_bind_checked(lv_obj_t * obj, lv_subject_t * subject);
348 
349 #if LV_USE_LABEL
350 /**
351  * Bind an integer, string, or pointer subject to a label.
352  * @param obj       pointer to a label
353  * @param subject   pointer to a subject
354  * @param fmt       optional format string with 1 format specifier (e.g. "%d °C")
355  *                  or NULL to bind the value directly.
356  * @return          pointer to the created observer
357  * @note            fmt == NULL can be used only with string and pointer subjects.
358  * @note            if the subject is a pointer must point to a `\0` terminated string.
359  */
360 lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt);
361 #endif
362 
363 #if LV_USE_ARC
364 /**
365  * Bind an integer subject to an arc's value
366  * @param obj       pointer to an arc
367  * @param subject   pointer to a subject
368  * @return          pointer to the created observer
369  */
370 lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject);
371 #endif
372 
373 #if LV_USE_SLIDER
374 /**
375  * Bind an integer subject to a slider's value
376  * @param obj       pointer to a slider
377  * @param subject   pointer to a subject
378  * @return          pointer to the created observer
379  */
380 lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject);
381 #endif
382 
383 #if LV_USE_ROLLER
384 /**
385  * Bind an integer subject to a roller's value
386  * @param obj       pointer to a roller
387  * @param subject   pointer to a subject
388  * @return          pointer to the created observer
389  */
390 lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject);
391 #endif
392 
393 #if LV_USE_DROPDOWN
394 /**
395  * Bind an integer subject to a dropdown's value
396  * @param obj       pointer to a drop down
397  * @param subject   pointer to a subject
398  * @return          pointer to the created observer
399  */
400 lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject);
401 #endif
402 
403 /**********************
404  *      MACROS
405  **********************/
406 
407 #endif /*LV_USE_OBSERVER*/
408 
409 #ifdef __cplusplus
410 } /*extern "C"*/
411 #endif
412 
413 #endif /*LV_OBSERVER_H*/
414