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