1 /**
2 * @file lv_msgbox.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_msgbox_private.h"
10 #include "../../core/lv_obj_private.h"
11 #include "../../core/lv_obj_class_private.h"
12 #if LV_USE_MSGBOX
13
14 #include "../label/lv_label.h"
15 #include "../button/lv_button.h"
16 #include "../image/lv_image.h"
17 #include "../../misc/lv_assert.h"
18 #include "../../display/lv_display.h"
19 #include "../../layouts/flex/lv_flex.h"
20 #include "../../stdlib/lv_string.h"
21
22 /*********************
23 * DEFINES
24 *********************/
25 #define LV_MSGBOX_FLAG_AUTO_PARENT LV_OBJ_FLAG_WIDGET_1 /*Mark that the parent was automatically created*/
26 #define MY_CLASS (&lv_msgbox_class)
27
28 /**********************
29 * TYPEDEFS
30 **********************/
31
32 /**********************
33 * STATIC PROTOTYPES
34 **********************/
35 static void msgbox_close_click_event_cb(lv_event_t * e);
36 static void msgbox_size_changed_event_cb(lv_event_t * e);
37
38 /**********************
39 * STATIC VARIABLES
40 **********************/
41 const lv_obj_class_t lv_msgbox_class = {
42 .base_class = &lv_obj_class,
43 .width_def = LV_DPI_DEF * 2,
44 .height_def = LV_SIZE_CONTENT,
45 .instance_size = sizeof(lv_msgbox_t),
46 .name = "msgbox",
47 };
48
49 const lv_obj_class_t lv_msgbox_header_class = {
50 .base_class = &lv_obj_class,
51 .width_def = LV_PCT(100),
52 .height_def = LV_DPI_DEF / 3,
53 .instance_size = sizeof(lv_obj_t),
54 .name = "msgbox-header",
55 };
56
57 const lv_obj_class_t lv_msgbox_content_class = {
58 .base_class = &lv_obj_class,
59 .width_def = LV_PCT(100),
60 .height_def = LV_SIZE_CONTENT,
61 .instance_size = sizeof(lv_obj_t),
62 .name = "msgbox-content",
63 };
64
65 const lv_obj_class_t lv_msgbox_footer_class = {
66 .base_class = &lv_obj_class,
67 .width_def = LV_PCT(100),
68 .height_def = LV_DPI_DEF / 3,
69 .instance_size = sizeof(lv_obj_t),
70 .name = "msgbox-footer",
71 };
72
73 const lv_obj_class_t lv_msgbox_footer_button_class = {
74 .base_class = &lv_obj_class,
75 .width_def = LV_SIZE_CONTENT,
76 .height_def = LV_PCT(100),
77 .instance_size = sizeof(lv_obj_t),
78 .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
79 .name = "msgbox-footer-button",
80 };
81
82 const lv_obj_class_t lv_msgbox_header_button_class = {
83 .base_class = &lv_obj_class,
84 .width_def = LV_DPI_DEF / 3,
85 .height_def = LV_PCT(100),
86 .instance_size = sizeof(lv_obj_t),
87 .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
88 .name = "msgbox-header-button",
89 };
90
91 const lv_obj_class_t lv_msgbox_backdrop_class = {
92 .base_class = &lv_obj_class,
93 .width_def = LV_PCT(100),
94 .height_def = LV_PCT(100),
95 .instance_size = sizeof(lv_obj_t),
96 .name = "msgbox-backdrop",
97 };
98
99 /**********************
100 * MACROS
101 **********************/
102
103 /**********************
104 * GLOBAL FUNCTIONS
105 **********************/
106
lv_msgbox_create(lv_obj_t * parent)107 lv_obj_t * lv_msgbox_create(lv_obj_t * parent)
108 {
109 LV_LOG_INFO("begin");
110 bool auto_parent = false;
111 if(parent == NULL) {
112 auto_parent = true;
113 parent = lv_obj_class_create_obj(&lv_msgbox_backdrop_class, lv_layer_top());
114 LV_ASSERT_MALLOC(parent);
115 lv_obj_class_init_obj(parent);
116 lv_obj_remove_flag(parent, LV_OBJ_FLAG_IGNORE_LAYOUT);
117 lv_obj_set_size(parent, LV_PCT(100), LV_PCT(100));
118 }
119
120 lv_obj_t * obj = lv_obj_class_create_obj(&lv_msgbox_class, parent);
121 LV_ASSERT_MALLOC(obj);
122 if(obj == NULL) return NULL;
123 lv_obj_class_init_obj(obj);
124 lv_msgbox_t * mbox = (lv_msgbox_t *)obj;
125 lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN);
126
127 if(auto_parent) lv_obj_add_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT);
128
129 mbox->content = lv_obj_class_create_obj(&lv_msgbox_content_class, obj);
130 LV_ASSERT_MALLOC(obj);
131 if(mbox->content == NULL) return NULL;
132 lv_obj_class_init_obj(mbox->content);
133 lv_obj_set_flex_flow(mbox->content, LV_FLEX_FLOW_COLUMN);
134 lv_obj_add_event_cb(obj, msgbox_size_changed_event_cb, LV_EVENT_SIZE_CHANGED, 0);
135
136 lv_obj_center(obj);
137 return obj;
138 }
139
lv_msgbox_add_title(lv_obj_t * obj,const char * title)140 lv_obj_t * lv_msgbox_add_title(lv_obj_t * obj, const char * title)
141 {
142 lv_msgbox_t * mbox = (lv_msgbox_t *)obj;
143 if(mbox->header == NULL) {
144 mbox->header = lv_obj_class_create_obj(&lv_msgbox_header_class, obj);
145 LV_ASSERT_MALLOC(obj);
146 if(mbox->header == NULL) return NULL;
147 lv_obj_class_init_obj(mbox->header);
148
149 lv_obj_set_size(mbox->header, lv_pct(100), lv_display_get_dpi(lv_obj_get_display(obj)) / 3);
150 lv_obj_set_flex_flow(mbox->header, LV_FLEX_FLOW_ROW);
151 lv_obj_set_flex_align(mbox->header, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
152 lv_obj_remove_flag(mbox->header, LV_OBJ_FLAG_SCROLLABLE);
153 lv_obj_move_to_index(mbox->header, 0);
154 }
155
156 if(mbox->title == NULL) {
157 mbox->title = lv_label_create(mbox->header);
158 lv_obj_set_flex_grow(mbox->title, 1);
159 }
160
161 lv_label_set_text(mbox->title, title);
162
163 return mbox->title;
164 }
165
lv_msgbox_add_header_button(lv_obj_t * obj,const void * icon)166 lv_obj_t * lv_msgbox_add_header_button(lv_obj_t * obj, const void * icon)
167 {
168 lv_msgbox_t * mbox = (lv_msgbox_t *)obj;
169 if(mbox->header == NULL) {
170 lv_msgbox_add_title(obj, ""); /*Just to push the buttons to the right*/
171 }
172
173 lv_obj_t * btn = lv_obj_class_create_obj(&lv_msgbox_header_button_class, mbox->header);
174 LV_ASSERT_MALLOC(obj);
175 if(btn == NULL) return NULL;
176 lv_obj_class_init_obj(btn);
177 lv_obj_remove_flag(btn, LV_OBJ_FLAG_SCROLLABLE);
178
179 if(icon) {
180 lv_obj_t * img = lv_image_create(btn);
181 lv_image_set_src(img, icon);
182 lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);
183 }
184
185 return btn;
186 }
187
lv_msgbox_add_text(lv_obj_t * obj,const char * text)188 lv_obj_t * lv_msgbox_add_text(lv_obj_t * obj, const char * text)
189 {
190 lv_msgbox_t * mbox = (lv_msgbox_t *)obj;
191
192 lv_obj_t * label = lv_label_create(mbox->content);
193 lv_label_set_text(label, text);
194 lv_obj_set_width(label, lv_pct(100));
195
196 return label;
197 }
198
lv_msgbox_add_footer_button(lv_obj_t * obj,const char * text)199 lv_obj_t * lv_msgbox_add_footer_button(lv_obj_t * obj, const char * text)
200 {
201 lv_msgbox_t * mbox = (lv_msgbox_t *)obj;
202 if(mbox->footer == NULL) {
203 mbox->footer = lv_obj_class_create_obj(&lv_msgbox_footer_class, obj);
204 LV_ASSERT_MALLOC(obj);
205 if(mbox->footer == NULL) return NULL;
206 lv_obj_class_init_obj(mbox->footer);
207
208 lv_obj_set_flex_flow(mbox->footer, LV_FLEX_FLOW_ROW);
209 lv_obj_set_flex_align(mbox->footer, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
210 lv_obj_remove_flag(mbox->footer, LV_OBJ_FLAG_SCROLLABLE);
211 }
212
213 lv_obj_t * btn = lv_obj_class_create_obj(&lv_msgbox_footer_button_class, mbox->footer);
214 LV_ASSERT_MALLOC(obj);
215 if(btn == NULL) return NULL;
216 lv_obj_class_init_obj(btn);
217 lv_obj_remove_flag(btn, LV_OBJ_FLAG_SCROLLABLE);
218
219 if(text) {
220 lv_obj_t * label = lv_label_create(btn);
221 lv_label_set_text(label, text);
222 lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
223 }
224
225 return btn;
226 }
227
lv_msgbox_add_close_button(lv_obj_t * obj)228 lv_obj_t * lv_msgbox_add_close_button(lv_obj_t * obj)
229 {
230 lv_obj_t * btn = lv_msgbox_add_header_button(obj, LV_SYMBOL_CLOSE);
231 lv_obj_add_event_cb(btn, msgbox_close_click_event_cb, LV_EVENT_CLICKED, NULL);
232 return btn;
233 }
234
lv_msgbox_get_header(lv_obj_t * obj)235 lv_obj_t * lv_msgbox_get_header(lv_obj_t * obj)
236 {
237 LV_ASSERT_OBJ(obj, MY_CLASS);
238 lv_msgbox_t * mbox = (lv_msgbox_t *)obj;
239 return mbox->header;
240 }
241
lv_msgbox_get_footer(lv_obj_t * obj)242 lv_obj_t * lv_msgbox_get_footer(lv_obj_t * obj)
243 {
244 LV_ASSERT_OBJ(obj, MY_CLASS);
245 lv_msgbox_t * mbox = (lv_msgbox_t *)obj;
246 return mbox->footer;
247 }
248
lv_msgbox_get_content(lv_obj_t * obj)249 lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj)
250 {
251 LV_ASSERT_OBJ(obj, MY_CLASS);
252 lv_msgbox_t * mbox = (lv_msgbox_t *)obj;
253 return mbox->content;
254 }
255
lv_msgbox_get_title(lv_obj_t * obj)256 lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj)
257 {
258 LV_ASSERT_OBJ(obj, MY_CLASS);
259 lv_msgbox_t * mbox = (lv_msgbox_t *)obj;
260 return mbox->title;
261 }
262
lv_msgbox_close(lv_obj_t * obj)263 void lv_msgbox_close(lv_obj_t * obj)
264 {
265 if(lv_obj_has_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_delete(lv_obj_get_parent(obj));
266 else lv_obj_delete(obj);
267 }
268
lv_msgbox_close_async(lv_obj_t * obj)269 void lv_msgbox_close_async(lv_obj_t * obj)
270 {
271 if(lv_obj_has_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_delete_async(lv_obj_get_parent(obj));
272 else lv_obj_delete_async(obj);
273 }
274
275 /**********************
276 * STATIC FUNCTIONS
277 **********************/
278
msgbox_close_click_event_cb(lv_event_t * e)279 static void msgbox_close_click_event_cb(lv_event_t * e)
280 {
281 lv_obj_t * btn = lv_event_get_current_target(e);
282 lv_obj_t * mbox = lv_obj_get_parent(lv_obj_get_parent(btn));
283 lv_msgbox_close(mbox);
284 }
285
msgbox_size_changed_event_cb(lv_event_t * e)286 static void msgbox_size_changed_event_cb(lv_event_t * e)
287 {
288 lv_obj_t * mbox = lv_event_get_target(e);
289 lv_obj_t * content = lv_msgbox_get_content(mbox);
290 bool is_msgbox_height_size_content = (lv_obj_get_style_height(mbox, 0) == LV_SIZE_CONTENT);
291 lv_obj_set_flex_grow(content, !is_msgbox_height_size_content);
292 }
293
294 #endif /*LV_USE_MSGBOX*/
295