1 /**
2  * @file lv_cb.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_checkbox.h"
10 #if LV_USE_CHECKBOX != 0
11 
12 #include "../lv_misc/lv_debug.h"
13 #include "../lv_core/lv_group.h"
14 #include "../lv_themes/lv_theme.h"
15 
16 /*********************
17  *      DEFINES
18  *********************/
19 #define LV_OBJX_NAME "lv_checkbox"
20 
21 /**********************
22  *      TYPEDEFS
23  **********************/
24 
25 /**********************
26  *  STATIC PROTOTYPES
27  **********************/
28 static lv_res_t lv_checkbox_signal(lv_obj_t * cb, lv_signal_t sign, void * param);
29 static lv_style_list_t * lv_checkbox_get_style(lv_obj_t * cb, uint8_t type);
30 
31 /**********************
32  *  STATIC VARIABLES
33  **********************/
34 static lv_signal_cb_t ancestor_signal;
35 
36 /**********************
37  *      MACROS
38  **********************/
39 
40 /**********************
41  *   GLOBAL FUNCTIONS
42  **********************/
43 
44 /**
45  * Create a check box objects
46  * @param par pointer to an object, it will be the parent of the new check box
47  * @param copy pointer to a check box object, if not NULL then the new object will be copied from it
48  * @return pointer to the created check box
49  */
lv_checkbox_create(lv_obj_t * par,const lv_obj_t * copy)50 lv_obj_t * lv_checkbox_create(lv_obj_t * par, const lv_obj_t * copy)
51 {
52     LV_LOG_TRACE("check box create started");
53 
54     /*Create the ancestor basic object*/
55     lv_obj_t * cb = lv_btn_create(par, copy);
56     LV_ASSERT_MEM(cb);
57     if(cb == NULL) return NULL;
58 
59     if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(cb);
60 
61     lv_checkbox_ext_t * ext = lv_obj_allocate_ext_attr(cb, sizeof(lv_checkbox_ext_t));
62     LV_ASSERT_MEM(ext);
63     if(ext == NULL) {
64         lv_obj_del(cb);
65         return NULL;
66     }
67 
68     ext->bullet = NULL;
69     ext->label  = NULL;
70 
71     lv_obj_set_signal_cb(cb, lv_checkbox_signal);
72 
73     /*Init the new checkbox object*/
74     if(copy == NULL) {
75         ext->bullet = lv_obj_create(cb, NULL);
76         lv_obj_set_click(ext->bullet, false);
77 
78         ext->label = lv_label_create(cb, NULL);
79 
80         lv_checkbox_set_text(cb, "Check box");
81         lv_btn_set_layout(cb, LV_LAYOUT_ROW_MID);
82         lv_btn_set_fit(cb, LV_FIT_TIGHT);
83         lv_btn_set_checkable(cb, true);
84         lv_obj_add_protect(cb, LV_PROTECT_PRESS_LOST);
85 
86         lv_theme_apply(cb, LV_THEME_CHECKBOX);
87 
88     }
89     else {
90         lv_checkbox_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
91         ext->bullet            = lv_obj_create(cb, copy_ext->bullet);
92         ext->label             = lv_label_create(cb, copy_ext->label);
93 
94         /*Refresh the style with new signal function*/
95         //        lv_obj_refresh_style(cb);
96     }
97 
98     LV_LOG_INFO("check box created");
99 
100     return cb;
101 }
102 
103 /*=====================
104  * Setter functions
105  *====================*/
106 
107 /**
108  * Set the text of a check box. `txt` will be copied and may be deallocated
109  * after this function returns.
110  * @param cb pointer to a check box
111  * @param txt the text of the check box. NULL to refresh with the current text.
112  */
lv_checkbox_set_text(lv_obj_t * cb,const char * txt)113 void lv_checkbox_set_text(lv_obj_t * cb, const char * txt)
114 {
115     LV_ASSERT_OBJ(cb, LV_OBJX_NAME);
116 
117     lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb);
118     lv_label_set_text(ext->label, txt);
119 }
120 
121 /**
122  * Set the text of a check box. `txt` must not be deallocated during the life
123  * of this checkbox.
124  * @param cb pointer to a check box
125  * @param txt the text of the check box. NULL to refresh with the current text.
126  */
lv_checkbox_set_text_static(lv_obj_t * cb,const char * txt)127 void lv_checkbox_set_text_static(lv_obj_t * cb, const char * txt)
128 {
129     LV_ASSERT_OBJ(cb, LV_OBJX_NAME);
130 
131     lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb);
132     lv_label_set_text_static(ext->label, txt);
133 }
134 
135 /**
136  * Set the state of the check box
137  * @param cb pointer to a check box object
138  * @param checked true: make the check box checked; false: make it unchecked
139  */
lv_checkbox_set_checked(lv_obj_t * cb,bool checked)140 void lv_checkbox_set_checked(lv_obj_t * cb, bool checked)
141 {
142     lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb);
143     lv_btn_set_state(cb, checked ? LV_BTN_STATE_CHECKED_RELEASED : LV_BTN_STATE_RELEASED);
144 
145     if(checked) {
146         lv_obj_add_state(ext->bullet, LV_STATE_CHECKED);
147         lv_obj_add_state(ext->label, LV_STATE_CHECKED);
148     }
149     else {
150         lv_obj_clear_state(ext->bullet, LV_STATE_CHECKED);
151         lv_obj_clear_state(ext->label, LV_STATE_CHECKED);
152     }
153 
154     lv_obj_clear_state(ext->bullet, LV_STATE_DISABLED);
155     lv_obj_clear_state(ext->label, LV_STATE_DISABLED);
156 
157 #if LV_USE_ANIMATION
158     lv_obj_finish_transitions(cb, LV_CHECKBOX_PART_BG);
159     lv_obj_finish_transitions(ext->bullet, LV_OBJ_PART_MAIN);
160 #endif
161 }
162 
163 
164 /**
165  * Make the check box inactive (disabled)
166  * @param cb pointer to a check box object
167  */
lv_checkbox_set_disabled(lv_obj_t * cb)168 void lv_checkbox_set_disabled(lv_obj_t * cb)
169 {
170     lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb);
171     lv_btn_set_state(cb, LV_BTN_STATE_DISABLED);
172 
173     lv_obj_add_state(ext->bullet, LV_STATE_DISABLED);
174     lv_obj_add_state(ext->label, LV_STATE_DISABLED);
175 
176 #if LV_USE_ANIMATION
177     lv_obj_finish_transitions(cb, LV_CHECKBOX_PART_BG);
178     lv_obj_finish_transitions(ext->bullet, LV_OBJ_PART_MAIN);
179 #endif
180 }
181 
182 /**
183  * Set the state of a check box
184  * @param cb pointer to a check box object
185  * @param state the new state of the check box (from lv_btn_state_t enum)
186  */
lv_checkbox_set_state(lv_obj_t * cb,lv_btn_state_t state)187 void lv_checkbox_set_state(lv_obj_t * cb, lv_btn_state_t state)
188 {
189     lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb);
190     lv_btn_set_state(cb, state);
191     lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CHECKBOX_PART_BG));
192     lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CHECKBOX_PART_BG));
193 
194 #if LV_USE_ANIMATION
195     lv_obj_finish_transitions(cb, LV_CHECKBOX_PART_BG);
196     lv_obj_finish_transitions(ext->bullet, LV_OBJ_PART_MAIN);
197 #endif
198 }
199 
200 /*=====================
201  * Getter functions
202  *====================*/
203 
204 /**
205  * Get the text of a check box
206  * @param cb pointer to check box object
207  * @return pointer to the text of the check box
208  */
lv_checkbox_get_text(const lv_obj_t * cb)209 const char * lv_checkbox_get_text(const lv_obj_t * cb)
210 {
211     LV_ASSERT_OBJ(cb, LV_OBJX_NAME);
212 
213     lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb);
214     return lv_label_get_text(ext->label);
215 }
216 
217 /**********************
218  *   STATIC FUNCTIONS
219  **********************/
220 
221 /**
222  * Signal function of the check box
223  * @param cb pointer to a check box object
224  * @param sign a signal type from lv_signal_t enum
225  * @param param pointer to a signal specific variable
226  * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
227  */
lv_checkbox_signal(lv_obj_t * cb,lv_signal_t sign,void * param)228 static lv_res_t lv_checkbox_signal(lv_obj_t * cb, lv_signal_t sign, void * param)
229 {
230     lv_res_t res;
231     if(sign == LV_SIGNAL_GET_STYLE) {
232         lv_get_style_info_t * info = param;
233         info->result = lv_checkbox_get_style(cb, info->part);
234         if(info->result != NULL) return LV_RES_OK;
235         else return ancestor_signal(cb, sign, param);
236     }
237 
238     /* Include the ancient signal function */
239     res = ancestor_signal(cb, sign, param);
240     if(res != LV_RES_OK) return res;
241     if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
242 
243     lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb);
244 
245     if(sign == LV_SIGNAL_STYLE_CHG) {
246         const lv_font_t * font = lv_obj_get_style_text_font(ext->label, LV_LABEL_PART_MAIN);
247         lv_coord_t line_height = lv_font_get_line_height(font);
248         lv_coord_t leftp = lv_obj_get_style_pad_left(cb, LV_CHECKBOX_PART_BULLET);
249         lv_coord_t rightp = lv_obj_get_style_pad_right(cb, LV_CHECKBOX_PART_BULLET);
250         lv_coord_t topp = lv_obj_get_style_pad_top(cb, LV_CHECKBOX_PART_BULLET);
251         lv_coord_t bottomp = lv_obj_get_style_pad_bottom(cb, LV_CHECKBOX_PART_BULLET);
252 
253         lv_obj_set_size(ext->bullet, line_height + leftp + rightp, line_height + topp + bottomp);
254         lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CHECKBOX_PART_BG));
255     }
256     else if(sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST ||
257             sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS) {
258         lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CHECKBOX_PART_BG));
259     }
260     else if(sign == LV_SIGNAL_CONTROL) {
261 #if LV_USE_GROUP
262         char c = *((char *)param);
263         if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN || c == LV_KEY_LEFT || c == LV_KEY_UP) {
264             /*Follow the backgrounds state with the bullet*/
265             lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CHECKBOX_PART_BG));
266         }
267 #endif
268     }
269 
270     return res;
271 }
272 
273 
lv_checkbox_get_style(lv_obj_t * cb,uint8_t type)274 static lv_style_list_t * lv_checkbox_get_style(lv_obj_t * cb, uint8_t type)
275 {
276     lv_style_list_t * style_dsc_p;
277 
278     lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb);
279     switch(type) {
280         case LV_CHECKBOX_PART_BG:
281             style_dsc_p = &cb->style_list;
282             break;
283         case LV_CHECKBOX_PART_BULLET:
284             style_dsc_p = lv_obj_get_style_list(ext->bullet, LV_BTN_PART_MAIN);
285             break;
286         default:
287             style_dsc_p = NULL;
288     }
289 
290     return style_dsc_p;
291 }
292 
293 #endif
294