1 /**
2  * @file lv_obj.h
3  *
4  */
5 
6 #ifndef LV_OBJ_H
7 #define LV_OBJ_H
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 /*********************
14  *      INCLUDES
15  *********************/
16 #include "../lv_conf_internal.h"
17 
18 #include <stddef.h>
19 #include <stdbool.h>
20 #include "../misc/lv_style.h"
21 #include "../misc/lv_types.h"
22 #include "../misc/lv_area.h"
23 #include "../misc/lv_color.h"
24 #include "../misc/lv_assert.h"
25 #include "../hal/lv_hal.h"
26 
27 /*********************
28  *      DEFINES
29  *********************/
30 
31 /**********************
32  *      TYPEDEFS
33  **********************/
34 
35 struct _lv_obj_t;
36 
37 /**
38  * Possible states of a widget.
39  * OR-ed values are possible
40  */
41 enum {
42     LV_STATE_DEFAULT     =  0x0000,
43     LV_STATE_CHECKED     =  0x0001,
44     LV_STATE_FOCUSED     =  0x0002,
45     LV_STATE_FOCUS_KEY   =  0x0004,
46     LV_STATE_EDITED      =  0x0008,
47     LV_STATE_HOVERED     =  0x0010,
48     LV_STATE_PRESSED     =  0x0020,
49     LV_STATE_SCROLLED    =  0x0040,
50     LV_STATE_DISABLED    =  0x0080,
51 
52     LV_STATE_USER_1      =  0x1000,
53     LV_STATE_USER_2      =  0x2000,
54     LV_STATE_USER_3      =  0x4000,
55     LV_STATE_USER_4      =  0x8000,
56 
57     LV_STATE_ANY = 0xFFFF,    /**< Special value can be used in some functions to target all states*/
58 };
59 
60 typedef uint16_t lv_state_t;
61 
62 /**
63  * The possible parts of widgets.
64  * The parts can be considered as the internal building block of the widgets.
65  * E.g. slider = background + indicator + knob
66  * Not all parts are used by every widget
67  */
68 enum {
69     LV_PART_MAIN         = 0x000000,   /**< A background like rectangle*/
70     LV_PART_SCROLLBAR    = 0x010000,   /**< The scrollbar(s)*/
71     LV_PART_INDICATOR    = 0x020000,   /**< Indicator, e.g. for slider, bar, switch, or the tick box of the checkbox*/
72     LV_PART_KNOB         = 0x030000,   /**< Like handle to grab to adjust the value*/
73     LV_PART_SELECTED     = 0x040000,   /**< Indicate the currently selected option or section*/
74     LV_PART_ITEMS        = 0x050000,   /**< Used if the widget has multiple similar elements (e.g. table cells)*/
75     LV_PART_TICKS        = 0x060000,   /**< Ticks on scale e.g. for a chart or meter*/
76     LV_PART_CURSOR       = 0x070000,   /**< Mark a specific place e.g. for text area's cursor or on a chart*/
77 
78     LV_PART_CUSTOM_FIRST = 0x080000,    /**< Extension point for custom widgets*/
79 
80     LV_PART_ANY          = 0x0F0000,    /**< Special value can be used in some functions to target all parts*/
81 };
82 
83 typedef uint32_t lv_part_t;
84 
85 /**
86  * On/Off features controlling the object's behavior.
87  * OR-ed values are possible
88  */
89 enum {
90     LV_OBJ_FLAG_HIDDEN          = (1L << 0),  /**< Make the object hidden. (Like it wasn't there at all)*/
91     LV_OBJ_FLAG_CLICKABLE       = (1L << 1),  /**< Make the object clickable by the input devices*/
92     LV_OBJ_FLAG_CLICK_FOCUSABLE = (1L << 2),  /**< Add focused state to the object when clicked*/
93     LV_OBJ_FLAG_CHECKABLE       = (1L << 3),  /**< Toggle checked state when the object is clicked*/
94     LV_OBJ_FLAG_SCROLLABLE      = (1L << 4),  /**< Make the object scrollable*/
95     LV_OBJ_FLAG_SCROLL_ELASTIC  = (1L << 5),  /**< Allow scrolling inside but with slower speed*/
96     LV_OBJ_FLAG_SCROLL_MOMENTUM = (1L << 6),  /**< Make the object scroll further when "thrown"*/
97     LV_OBJ_FLAG_SCROLL_ONE      = (1L << 7),  /**< Allow scrolling only one snappable children*/
98     LV_OBJ_FLAG_SCROLL_CHAIN_HOR = (1L << 8), /**< Allow propagating the horizontal scroll to a parent*/
99     LV_OBJ_FLAG_SCROLL_CHAIN_VER = (1L << 9), /**< Allow propagating the vertical scroll to a parent*/
100     LV_OBJ_FLAG_SCROLL_CHAIN     = (LV_OBJ_FLAG_SCROLL_CHAIN_HOR | LV_OBJ_FLAG_SCROLL_CHAIN_VER),
101     LV_OBJ_FLAG_SCROLL_ON_FOCUS = (1L << 10),  /**< Automatically scroll object to make it visible when focused*/
102     LV_OBJ_FLAG_SCROLL_WITH_ARROW  = (1L << 11), /**< Allow scrolling the focused object with arrow keys*/
103     LV_OBJ_FLAG_SNAPPABLE       = (1L << 12), /**< If scroll snap is enabled on the parent it can snap to this object*/
104     LV_OBJ_FLAG_PRESS_LOCK      = (1L << 13), /**< Keep the object pressed even if the press slid from the object*/
105     LV_OBJ_FLAG_EVENT_BUBBLE    = (1L << 14), /**< Propagate the events to the parent too*/
106     LV_OBJ_FLAG_GESTURE_BUBBLE  = (1L << 15), /**< Propagate the gestures to the parent*/
107     LV_OBJ_FLAG_ADV_HITTEST     = (1L << 16), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/
108     LV_OBJ_FLAG_IGNORE_LAYOUT   = (1L << 17), /**< Make the object position-able by the layouts*/
109     LV_OBJ_FLAG_FLOATING        = (1L << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/
110     LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1L << 19), /**< Do not clip the children's content to the parent's boundary*/
111 
112     LV_OBJ_FLAG_LAYOUT_1        = (1L << 23), /**< Custom flag, free to use by layouts*/
113     LV_OBJ_FLAG_LAYOUT_2        = (1L << 24), /**< Custom flag, free to use by layouts*/
114 
115     LV_OBJ_FLAG_WIDGET_1        = (1L << 25), /**< Custom flag, free to use by widget*/
116     LV_OBJ_FLAG_WIDGET_2        = (1L << 26), /**< Custom flag, free to use by widget*/
117     LV_OBJ_FLAG_USER_1          = (1L << 27), /**< Custom flag, free to use by user*/
118     LV_OBJ_FLAG_USER_2          = (1L << 28), /**< Custom flag, free to use by user*/
119     LV_OBJ_FLAG_USER_3          = (1L << 29), /**< Custom flag, free to use by user*/
120     LV_OBJ_FLAG_USER_4          = (1L << 30), /**< Custom flag, free to use by user*/
121 
122 };
123 
124 
125 typedef uint32_t lv_obj_flag_t;
126 
127 /**
128  * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_obj_class`
129  * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END`
130  */
131 typedef enum {
132     LV_OBJ_DRAW_PART_RECTANGLE,  /**< The main rectangle*/
133     LV_OBJ_DRAW_PART_BORDER_POST,/**< The border if style_border_post = true*/
134     LV_OBJ_DRAW_PART_SCROLLBAR,  /**< The scrollbar*/
135 } lv_obj_draw_part_type_t;
136 
137 #include "lv_obj_tree.h"
138 #include "lv_obj_pos.h"
139 #include "lv_obj_scroll.h"
140 #include "lv_obj_style.h"
141 #include "lv_obj_draw.h"
142 #include "lv_obj_class.h"
143 #include "lv_event.h"
144 #include "lv_group.h"
145 
146 /**
147  * Make the base object's class publicly available.
148  */
149 extern const lv_obj_class_t lv_obj_class;
150 
151 /**
152  * Special, rarely used attributes.
153  * They are allocated automatically if any elements is set.
154  */
155 typedef struct {
156     struct _lv_obj_t ** children;       /**< Store the pointer of the children in an array.*/
157     uint32_t child_cnt;                 /**< Number of children*/
158     lv_group_t * group_p;
159 
160     struct _lv_event_dsc_t * event_dsc; /**< Dynamically allocated event callback and user data array*/
161     lv_point_t scroll;                  /**< The current X/Y scroll offset*/
162 
163     lv_coord_t ext_click_pad;           /**< Extra click padding in all direction*/
164     lv_coord_t ext_draw_size;           /**< EXTend the size in every direction for drawing.*/
165 
166     lv_scrollbar_mode_t scrollbar_mode : 2; /**< How to display scrollbars*/
167     lv_scroll_snap_t scroll_snap_x : 2;     /**< Where to align the snappable children horizontally*/
168     lv_scroll_snap_t scroll_snap_y : 2;     /**< Where to align the snappable children vertically*/
169     lv_dir_t scroll_dir : 4;                /**< The allowed scroll direction(s)*/
170     uint8_t event_dsc_cnt : 6;              /**< Number of event callbacks stored in `event_dsc` array*/
171     uint8_t layer_type : 2;    /**< Cache the layer type here. Element of @lv_intermediate_layer_type_t */
172 } _lv_obj_spec_attr_t;
173 
174 typedef struct _lv_obj_t {
175     const lv_obj_class_t * class_p;
176     struct _lv_obj_t * parent;
177     _lv_obj_spec_attr_t * spec_attr;
178     _lv_obj_style_t * styles;
179 #if LV_USE_USER_DATA
180     void * user_data;
181 #endif
182     lv_area_t coords;
183     lv_obj_flag_t flags;
184     lv_state_t state;
185     uint16_t layout_inv : 1;
186     uint16_t readjust_scroll_after_layout : 1;
187     uint16_t scr_layout_inv : 1;
188     uint16_t skip_trans : 1;
189     uint16_t style_cnt  : 6;
190     uint16_t h_layout   : 1;
191     uint16_t w_layout   : 1;
192     uint16_t being_deleted   : 1;
193 } lv_obj_t;
194 
195 
196 /**********************
197  * GLOBAL PROTOTYPES
198  **********************/
199 
200 /**
201  * Initialize LVGL library.
202  * Should be called before any other LVGL related function.
203  */
204 void lv_init(void);
205 
206 #if LV_ENABLE_GC || !LV_MEM_CUSTOM
207 
208 /**
209  * Deinit the 'lv' library
210  * Currently only implemented when not using custom allocators, or GC is enabled.
211  */
212 void lv_deinit(void);
213 
214 #endif
215 
216 /**
217  * Returns whether the 'lv' library is currently initialized
218  */
219 bool lv_is_initialized(void);
220 
221 /**
222  * Create a base object (a rectangle)
223  * @param parent    pointer to a parent object. If NULL then a screen will be created.
224  * @return          pointer to the new object
225  */
226 lv_obj_t * lv_obj_create(lv_obj_t * parent);
227 
228 
229 /*=====================
230  * Setter functions
231  *====================*/
232 
233 /**
234  * Set one or more flags
235  * @param obj   pointer to an object
236  * @param f     R-ed values from `lv_obj_flag_t` to set.
237  */
238 void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f);
239 
240 /**
241  * Clear one or more flags
242  * @param obj   pointer to an object
243  * @param f     OR-ed values from `lv_obj_flag_t` to set.
244  */
245 void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f);
246 
247 
248 /**
249  * Add one or more states to the object. The other state bits will remain unchanged.
250  * If specified in the styles, transition animation will be started from the previous state to the current.
251  * @param obj       pointer to an object
252  * @param state     the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
253  */
254 void lv_obj_add_state(lv_obj_t * obj, lv_state_t state);
255 
256 /**
257  * Remove one or more states to the object. The other state bits will remain unchanged.
258  * If specified in the styles, transition animation will be started from the previous state to the current.
259  * @param obj       pointer to an object
260  * @param state     the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
261  */
262 void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state);
263 
264 /**
265  * Set the user_data field of the object
266  * @param obj   pointer to an object
267  * @param user_data   pointer to the new user_data.
268  */
269 #if LV_USE_USER_DATA
lv_obj_set_user_data(lv_obj_t * obj,void * user_data)270 static inline void lv_obj_set_user_data(lv_obj_t * obj, void * user_data)
271 {
272     obj->user_data = user_data;
273 }
274 #endif
275 
276 /*=======================
277  * Getter functions
278  *======================*/
279 
280 /**
281  * Check if a given flag or all the given flags are set on an object.
282  * @param obj   pointer to an object
283  * @param f     the flag(s) to check (OR-ed values can be used)
284  * @return      true: all flags are set; false: not all flags are set
285  */
286 bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f);
287 
288 /**
289  * Check if a given flag or any of the flags are set on an object.
290  * @param obj   pointer to an object
291  * @param f     the flag(s) to check (OR-ed values can be used)
292  * @return      true: at lest one flag flag is set; false: none of the flags are set
293  */
294 bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f);
295 
296 /**
297  * Get the state of an object
298  * @param obj   pointer to an object
299  * @return      the state (OR-ed values from `lv_state_t`)
300  */
301 lv_state_t lv_obj_get_state(const lv_obj_t * obj);
302 
303 /**
304  * Check if the object is in a given state or not.
305  * @param obj       pointer to an object
306  * @param state     a state or combination of states to check
307  * @return          true: `obj` is in `state`; false: `obj` is not in `state`
308  */
309 bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state);
310 
311 /**
312  * Get the group of the object
313  * @param       obj pointer to an object
314  * @return      the pointer to group of the object
315  */
316 void * lv_obj_get_group(const lv_obj_t * obj);
317 
318 /**
319  * Get the user_data field of the object
320  * @param obj   pointer to an object
321  * @return      the pointer to the user_data of the object
322  */
323 #if LV_USE_USER_DATA
lv_obj_get_user_data(lv_obj_t * obj)324 static inline void * lv_obj_get_user_data(lv_obj_t * obj)
325 {
326     return obj->user_data;
327 }
328 #endif
329 
330 /*=======================
331  * Other functions
332  *======================*/
333 
334 /**
335  * Allocate special data for an object if not allocated yet.
336  * @param obj   pointer to an object
337  */
338 void lv_obj_allocate_spec_attr(lv_obj_t * obj);
339 
340 /**
341  * Check the type of obj.
342  * @param obj       pointer to an object
343  * @param class_p   a class to check (e.g. `lv_slider_class`)
344  * @return          true: `class_p` is the `obj` class.
345  */
346 bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p);
347 
348 /**
349  * Check if any object has a given class (type).
350  * It checks the ancestor classes too.
351  * @param obj       pointer to an object
352  * @param class_p   a class to check (e.g. `lv_slider_class`)
353  * @return          true: `obj` has the given class
354  */
355 bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p);
356 
357 /**
358  * Get the class (type) of the object
359  * @param obj   pointer to an object
360  * @return      the class (type) of the object
361  */
362 const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj);
363 
364 /**
365  * Check if any object is still "alive".
366  * @param obj       pointer to an object
367  * @return          true: valid
368  */
369 bool lv_obj_is_valid(const lv_obj_t * obj);
370 
371 /**
372  * Scale the given number of pixels (a distance or size) relative to a 160 DPI display
373  * considering the DPI of the `obj`'s display.
374  * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
375  * DPI of the display.
376  * @param obj   an object whose display's dpi should be considered
377  * @param n     the number of pixels to scale
378  * @return      `n x current_dpi/160`
379  */
lv_obj_dpx(const lv_obj_t * obj,lv_coord_t n)380 static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n)
381 {
382     return _LV_DPX_CALC(lv_disp_get_dpi(lv_obj_get_disp(obj)), n);
383 }
384 
385 /**********************
386  *      MACROS
387  **********************/
388 
389 #if LV_USE_ASSERT_OBJ
390 #  define LV_ASSERT_OBJ(obj_p, obj_class)                                                               \
391     do {                                                                                                \
392         LV_ASSERT_MSG(obj_p != NULL, "The object is NULL");                                             \
393         LV_ASSERT_MSG(lv_obj_has_class(obj_p, obj_class) == true, "Incompatible object type.");         \
394         LV_ASSERT_MSG(lv_obj_is_valid(obj_p)  == true, "The object is invalid, deleted or corrupted?"); \
395     } while(0)
396 # else
397 #  define LV_ASSERT_OBJ(obj_p, obj_class) do{}while(0)
398 #endif
399 
400 #if LV_USE_LOG && LV_LOG_TRACE_OBJ_CREATE
401 #  define LV_TRACE_OBJ_CREATE(...) LV_LOG_TRACE(__VA_ARGS__)
402 #else
403 #  define LV_TRACE_OBJ_CREATE(...)
404 #endif
405 
406 
407 #ifdef __cplusplus
408 } /*extern "C"*/
409 #endif
410 
411 #endif /*LV_OBJ_H*/
412