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