diff --git a/demos/keypad_encoder/lv_demo_keypad_encoder.c b/demos/keypad_encoder/lv_demo_keypad_encoder.c index 96ee43561..36e1b067f 100644 --- a/demos/keypad_encoder/lv_demo_keypad_encoder.c +++ b/demos/keypad_encoder/lv_demo_keypad_encoder.c @@ -162,11 +162,14 @@ static void text_input_create(lv_obj_t * parent) static void msgbox_create(void) { - static const char * buttons[] = {"Ok", "Cancel", ""}; - lv_obj_t * mbox = lv_msgbox_create(NULL, "Hi", "Welcome to the keyboard and encoder demo", buttons, false); - lv_obj_add_event_cb(mbox, msgbox_event_cb, LV_EVENT_ALL, NULL); - lv_group_focus_obj(lv_msgbox_get_buttons(mbox)); - lv_obj_add_state(lv_msgbox_get_buttons(mbox), LV_STATE_FOCUS_KEY); + lv_obj_t * mbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(mbox, "Hi"); + lv_msgbox_add_text(mbox, "Welcome to the keyboard and encoder demo"); + + lv_obj_t * btn = lv_msgbox_add_footer_button(mbox, "Ok"); + lv_obj_add_event_cb(btn, msgbox_event_cb, LV_EVENT_CLICKED, mbox); + lv_group_focus_obj(btn); + lv_obj_add_state(btn, LV_STATE_FOCUS_KEY); lv_group_focus_freeze(g, true); lv_obj_align(mbox, LV_ALIGN_CENTER, 0, 0); @@ -178,19 +181,12 @@ static void msgbox_create(void) static void msgbox_event_cb(lv_event_t * e) { - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * msgbox = lv_event_get_current_target(e); + lv_obj_t * msgbox = lv_event_get_user_data(e); - if(code == LV_EVENT_VALUE_CHANGED) { - const char * txt = lv_msgbox_get_active_button_text(msgbox); - if(txt) { - lv_msgbox_close(msgbox); - lv_group_focus_freeze(g, false); - lv_group_focus_obj(lv_obj_get_child(t1, 0)); - lv_obj_scroll_to(t1, 0, 0, LV_ANIM_OFF); - - } - } + lv_msgbox_close(msgbox); + lv_group_focus_freeze(g, false); + lv_group_focus_obj(lv_obj_get_child(t1, 0)); + lv_obj_scroll_to(t1, 0, 0, LV_ANIM_OFF); } static void ta_event_cb(lv_event_t * e) diff --git a/demos/stress/lv_demo_stress.c b/demos/stress/lv_demo_stress.c index e6570da08..64399b97f 100644 --- a/demos/stress/lv_demo_stress.c +++ b/demos/stress/lv_demo_stress.c @@ -32,7 +32,6 @@ static void obj_test_task_cb(lv_timer_t * tmr); **********************/ static lv_obj_t * main_page; static lv_obj_t * ta; -static const char * mbox_buttons[] = {"Ok", "Cancel", ""}; static uint32_t mem_free_start = 0; static int16_t g_state = -1; @@ -241,7 +240,12 @@ static void obj_test_task_cb(lv_timer_t * tmr) break; case 14: - obj = lv_msgbox_create(NULL, "Title", "Some text on the message box with average length", mbox_buttons, true); + obj = lv_msgbox_create(NULL); + lv_msgbox_add_title(obj, "Title"); + lv_msgbox_add_header_button(obj, LV_SYMBOL_AUDIO); + lv_msgbox_add_text(obj, "Some text"); + lv_msgbox_add_footer_button(obj, "Button 1"); + lv_msgbox_add_footer_button(obj, "Button 2"); { lv_timer_t * msgbox_tmr = lv_timer_create(msgbox_delete, LV_DEMO_STRESS_TIME_STEP * 5 + 30, obj); lv_timer_set_repeat_count(msgbox_tmr, 1); diff --git a/examples/widgets/menu/lv_example_menu_2.c b/examples/widgets/menu/lv_example_menu_2.c index 975b15995..71f9162ee 100644 --- a/examples/widgets/menu/lv_example_menu_2.c +++ b/examples/widgets/menu/lv_example_menu_2.c @@ -7,8 +7,10 @@ static void back_event_handler(lv_event_t * e) lv_obj_t * menu = lv_event_get_user_data(e); if(lv_menu_back_button_is_root(menu, obj)) { - lv_obj_t * mbox1 = lv_msgbox_create(NULL, "Hello", "Root back btn click.", NULL, true); - lv_obj_center(mbox1); + lv_obj_t * mbox1 = lv_msgbox_create(NULL); + lv_msgbox_add_title(mbox1, "Hello"); + lv_msgbox_add_text(mbox1, "Root back btn click."); + lv_msgbox_add_close_button(mbox1); } } diff --git a/examples/widgets/menu/lv_example_menu_5.c b/examples/widgets/menu/lv_example_menu_5.c index 6630917e2..ee0cc377d 100644 --- a/examples/widgets/menu/lv_example_menu_5.c +++ b/examples/widgets/menu/lv_example_menu_5.c @@ -117,8 +117,10 @@ static void back_event_handler(lv_event_t * e) lv_obj_t * menu = lv_event_get_user_data(e); if(lv_menu_back_button_is_root(menu, obj)) { - lv_obj_t * mbox1 = lv_msgbox_create(NULL, "Hello", "Root back btn click.", NULL, true); - lv_obj_center(mbox1); + lv_obj_t * mbox1 = lv_msgbox_create(NULL); + lv_msgbox_add_title(mbox1, "Hello"); + lv_msgbox_add_text(mbox1, "Root back btn click."); + lv_msgbox_add_close_button(mbox1); } } diff --git a/examples/widgets/msgbox/lv_example_msgbox_1.c b/examples/widgets/msgbox/lv_example_msgbox_1.c index c41fb84db..cc3bb6e96 100644 --- a/examples/widgets/msgbox/lv_example_msgbox_1.c +++ b/examples/widgets/msgbox/lv_example_msgbox_1.c @@ -3,18 +3,26 @@ static void event_cb(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); - LV_UNUSED(obj); - LV_LOG_USER("Button %s clicked", lv_msgbox_get_active_button_text(obj)); + lv_obj_t * btn = lv_event_get_target(e); + lv_obj_t * label = lv_obj_get_child(btn, 0); + LV_LOG_USER("Button %s clicked", lv_label_get_text(label)); } void lv_example_msgbox_1(void) { - static const char * buttons[] = {"Apply", "Close", ""}; + lv_obj_t * mbox1 = lv_msgbox_create(NULL); - lv_obj_t * mbox1 = lv_msgbox_create(NULL, "Hello", "This is a message box with two buttons.", buttons, true); - lv_obj_add_event_cb(mbox1, event_cb, LV_EVENT_VALUE_CHANGED, NULL); - lv_obj_center(mbox1); + lv_msgbox_add_title(mbox1, "Hello"); + + lv_msgbox_add_text(mbox1, "This is a message box with two buttons."); + lv_msgbox_add_close_button(mbox1); + + lv_obj_t * btn; + btn = lv_msgbox_add_footer_button(mbox1, "Apply"); + lv_obj_add_event_cb(btn, event_cb, LV_EVENT_CLICKED, NULL); + btn = lv_msgbox_add_footer_button(mbox1, "Cancel"); + lv_obj_add_event_cb(btn, event_cb, LV_EVENT_CLICKED, NULL); + return; } #endif diff --git a/src/themes/default/lv_theme_default.c b/src/themes/default/lv_theme_default.c index ef496cde7..fd1543544 100644 --- a/src/themes/default/lv_theme_default.c +++ b/src/themes/default/lv_theme_default.c @@ -129,7 +129,7 @@ typedef struct { #endif #if LV_USE_MSGBOX - lv_style_t msgbox_bg, msgbox_button_bg, msgbox_backdrop_bg; + lv_style_t msgbox_backdrop_bg; #endif #if LV_USE_KEYBOARD @@ -585,13 +585,6 @@ static void style_init(struct _my_theme_t * theme) #endif #if LV_USE_MSGBOX - /*To add space for for the button shadow*/ - style_init_reset(&theme->styles.msgbox_button_bg); - lv_style_set_pad_all(&theme->styles.msgbox_button_bg, _LV_DPX_CALC(theme->disp_dpi, 4)); - - style_init_reset(&theme->styles.msgbox_bg); - lv_style_set_max_width(&theme->styles.msgbox_bg, lv_pct(100)); - style_init_reset(&theme->styles.msgbox_backdrop_bg); lv_style_set_bg_color(&theme->styles.msgbox_backdrop_bg, lv_palette_main(LV_PALETTE_GREY)); lv_style_set_bg_opa(&theme->styles.msgbox_backdrop_bg, LV_OPA_100); @@ -852,19 +845,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_BTNMATRIX else if(lv_obj_check_type(obj, &lv_buttonmatrix_class)) { -#if LV_USE_MSGBOX - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { - lv_obj_add_style(obj, &theme->styles.msgbox_button_bg, 0); - lv_obj_add_style(obj, &theme->styles.pad_gap, 0); - lv_obj_add_style(obj, &theme->styles.btn, LV_PART_ITEMS); - lv_obj_add_style(obj, &theme->styles.pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_ITEMS | LV_STATE_CHECKED); - lv_obj_add_style(obj, &theme->styles.bg_color_primary_muted, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &theme->styles.bg_color_secondary_muted, LV_PART_ITEMS | LV_STATE_EDITED); - return; - } -#endif #if LV_USE_CALENDAR if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { @@ -1161,13 +1141,42 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_MSGBOX else if(lv_obj_check_type(obj, &lv_msgbox_class)) { lv_obj_add_style(obj, &theme->styles.card, 0); - lv_obj_add_style(obj, &theme->styles.msgbox_bg, 0); + lv_obj_add_style(obj, &theme->styles.pad_zero, 0); return; } else if(lv_obj_check_type(obj, &lv_msgbox_backdrop_class)) { lv_obj_add_style(obj, &theme->styles.msgbox_backdrop_bg, 0); + return; } + else if(lv_obj_check_type(obj, &lv_msgbox_header_class)) { + lv_obj_add_style(obj, &theme->styles.pad_tiny, 0); + lv_obj_add_style(obj, &theme->styles.bg_color_grey, 0); + return; + } + else if(lv_obj_check_type(obj, &lv_msgbox_footer_class)) { + lv_obj_add_style(obj, &theme->styles.pad_tiny, 0); + return; + } + else if(lv_obj_check_type(obj, &lv_msgbox_header_button_class) || + lv_obj_check_type(obj, &lv_msgbox_footer_button_class)) { + lv_obj_add_style(obj, &theme->styles.btn, 0); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, 0); + lv_obj_add_style(obj, &theme->styles.transition_delayed, 0); + lv_obj_add_style(obj, &theme->styles.pressed, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.transition_normal, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.bg_color_secondary, LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.disabled, LV_STATE_DISABLED); + return; + } + + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { + lv_obj_add_style(obj, &theme->styles.pad_tiny, 0); + return; + } + #endif + #if LV_USE_SPINBOX else if(lv_obj_check_type(obj, &lv_spinbox_class)) { lv_obj_add_style(obj, &theme->styles.card, 0); diff --git a/src/widgets/label/lv_label.c b/src/widgets/label/lv_label.c index 428bdba54..74e436851 100644 --- a/src/widgets/label/lv_label.c +++ b/src/widgets/label/lv_label.c @@ -25,7 +25,7 @@ *********************/ #define MY_CLASS &lv_label_class -#define LV_LABEL_DEF_SCROLL_SPEED lv_anim_speed_clamped(40, 300, 100 * 1000) +#define LV_LABEL_DEF_SCROLL_SPEED lv_anim_speed_clamped(40, 300, 10000) #define LV_LABEL_SCROLL_DELAY 300 #define LV_LABEL_DOT_END_INV 0xFFFFFFFF #define LV_LABEL_HINT_HEIGHT_LIMIT 1024 /*Enable "hint" to buffer info about labels larger than this. (Speed up drawing)*/ diff --git a/src/widgets/msgbox/lv_msgbox.c b/src/widgets/msgbox/lv_msgbox.c index 810b2b21a..a7e59b4e4 100644 --- a/src/widgets/msgbox/lv_msgbox.c +++ b/src/widgets/msgbox/lv_msgbox.c @@ -11,7 +11,7 @@ #include "../label/lv_label.h" #include "../button/lv_button.h" -#include "../buttonmatrix/lv_buttonmatrix.h" +#include "../image/lv_image.h" #include "../../misc/lv_assert.h" #include "../../display/lv_display.h" #include "../../layouts/flex/lv_flex.h" @@ -43,6 +43,14 @@ const lv_obj_class_t lv_msgbox_class = { .name = "msgbox", }; +const lv_obj_class_t lv_msgbox_header_class = { + .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_DPI_DEF / 3, + .instance_size = sizeof(lv_obj_t), + .name = "msgbox-header", +}; + const lv_obj_class_t lv_msgbox_content_class = { .base_class = &lv_obj_class, .width_def = LV_PCT(100), @@ -51,6 +59,32 @@ const lv_obj_class_t lv_msgbox_content_class = { .name = "msgbox-content", }; +const lv_obj_class_t lv_msgbox_footer_class = { + .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_DPI_DEF / 3, + .instance_size = sizeof(lv_obj_t), + .name = "msgbox-footer", +}; + +const lv_obj_class_t lv_msgbox_footer_button_class = { + .base_class = &lv_obj_class, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_PCT(100), + .instance_size = sizeof(lv_obj_t), + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .name = "msgbox-footer-button", +}; + +const lv_obj_class_t lv_msgbox_header_button_class = { + .base_class = &lv_obj_class, + .width_def = LV_DPI_DEF / 3, + .height_def = LV_PCT(100), + .instance_size = sizeof(lv_obj_t), + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .name = "msgbox-header-button", +}; + const lv_obj_class_t lv_msgbox_backdrop_class = { .base_class = &lv_obj_class, .width_def = LV_PCT(100), @@ -67,8 +101,7 @@ const lv_obj_class_t lv_msgbox_backdrop_class = { * GLOBAL FUNCTIONS **********************/ -lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], - bool add_close_btn) +lv_obj_t * lv_msgbox_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); bool auto_parent = false; @@ -86,86 +119,123 @@ lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * if(obj == NULL) return NULL; lv_obj_class_init_obj(obj); lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); if(auto_parent) lv_obj_add_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT); - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW_WRAP); - - bool has_title = title && lv_strlen(title) > 0; - - /*When a close button is required, we need the empty label as spacer to push the button to the right*/ - if(add_close_btn || has_title) { - mbox->title = lv_label_create(obj); - lv_label_set_text(mbox->title, has_title ? title : ""); - lv_label_set_long_mode(mbox->title, LV_LABEL_LONG_SCROLL_CIRCULAR); - if(add_close_btn) lv_obj_set_flex_grow(mbox->title, 1); - else lv_obj_set_width(mbox->title, LV_PCT(100)); - } - - if(add_close_btn) { - mbox->close_btn = lv_button_create(obj); - lv_obj_set_ext_click_area(mbox->close_btn, LV_DPX(10)); - lv_obj_add_event_cb(mbox->close_btn, msgbox_close_click_event_cb, LV_EVENT_CLICKED, NULL); - lv_obj_t * label = lv_label_create(mbox->close_btn); - lv_label_set_text(label, LV_SYMBOL_CLOSE); - const lv_font_t * font = lv_obj_get_style_text_font(mbox->close_btn, LV_PART_MAIN); - int32_t close_button_size = lv_font_get_line_height(font) + LV_DPX(10); - lv_obj_set_size(mbox->close_btn, close_button_size, close_button_size); - lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); - } - mbox->content = lv_obj_class_create_obj(&lv_msgbox_content_class, obj); LV_ASSERT_MALLOC(obj); if(mbox->content == NULL) return NULL; lv_obj_class_init_obj(mbox->content); + lv_obj_set_flex_flow(mbox->content, LV_FLEX_FLOW_COLUMN); - bool has_txt = txt && lv_strlen(txt) > 0; - if(has_txt) { - mbox->text = lv_label_create(mbox->content); - lv_label_set_text(mbox->text, txt); - lv_label_set_long_mode(mbox->text, LV_LABEL_LONG_WRAP); - lv_obj_set_width(mbox->text, lv_pct(100)); - } - - if(btn_txts) { - mbox->buttons = lv_buttonmatrix_create(obj); - lv_buttonmatrix_set_map(mbox->buttons, btn_txts); - lv_buttonmatrix_set_button_ctrl_all(mbox->buttons, LV_BUTTONMATRIX_CTRL_CLICK_TRIG | LV_BUTTONMATRIX_CTRL_NO_REPEAT); - - uint32_t btn_cnt = 0; - while(btn_txts[btn_cnt] && btn_txts[btn_cnt][0] != '\0') { - btn_cnt++; - } - - const lv_font_t * font = lv_obj_get_style_text_font(mbox->buttons, LV_PART_ITEMS); - int32_t btn_h = lv_font_get_line_height(font) + LV_DPI_DEF / 10; - lv_obj_set_size(mbox->buttons, btn_cnt * (2 * LV_DPI_DEF / 3), btn_h); - lv_obj_set_style_max_width(mbox->buttons, lv_pct(100), 0); - lv_obj_add_flag(mbox->buttons, LV_OBJ_FLAG_EVENT_BUBBLE); /*To see the event directly on the message box*/ - } - + lv_obj_center(obj); return obj; } -lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj) +lv_obj_t * lv_msgbox_add_title(lv_obj_t * obj, const char * title) { - LV_ASSERT_OBJ(obj, MY_CLASS); lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + if(mbox->header == NULL) { + mbox->header = lv_obj_class_create_obj(&lv_msgbox_header_class, obj); + LV_ASSERT_MALLOC(obj); + if(mbox->header == NULL) return NULL; + lv_obj_class_init_obj(mbox->header); + + lv_obj_set_size(mbox->header, lv_pct(100), lv_display_get_dpi(lv_obj_get_disp(obj)) / 3); + lv_obj_set_flex_flow(mbox->header, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(mbox->header, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_move_to_index(mbox->header, 0); + } + + if(mbox->title == NULL) { + mbox->title = lv_label_create(mbox->header); + lv_obj_set_flex_grow(mbox->title, 1); + } + + lv_label_set_text(mbox->title, title); + return mbox->title; } -lv_obj_t * lv_msgbox_get_close_button(lv_obj_t * obj) +lv_obj_t * lv_msgbox_add_header_button(lv_obj_t * obj, const void * icon) { - LV_ASSERT_OBJ(obj, MY_CLASS); lv_msgbox_t * mbox = (lv_msgbox_t *)obj; - return mbox->close_btn; + if(mbox->header == NULL) { + lv_msgbox_add_title(obj, ""); /*Just to push the buttons to the right*/ + } + + lv_obj_t * btn = lv_obj_class_create_obj(&lv_msgbox_header_button_class, mbox->header); + LV_ASSERT_MALLOC(obj); + if(btn == NULL) return NULL; + lv_obj_class_init_obj(btn); + + if(icon) { + lv_obj_t * img = lv_image_create(btn); + lv_image_set_src(img, icon); + lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); + } + + return btn; } -lv_obj_t * lv_msgbox_get_text(lv_obj_t * obj) +lv_obj_t * lv_msgbox_add_text(lv_obj_t * obj, const char * text) +{ + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + + lv_obj_t * label = lv_label_create(mbox->content); + lv_label_set_text(label, text); + lv_obj_set_width(label, lv_pct(100)); + + return label; +} + +lv_obj_t * lv_msgbox_add_footer_button(lv_obj_t * obj, const char * text) +{ + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + if(mbox->footer == NULL) { + mbox->footer = lv_obj_class_create_obj(&lv_msgbox_footer_class, obj); + LV_ASSERT_MALLOC(obj); + if(mbox->footer == NULL) return NULL; + lv_obj_class_init_obj(mbox->footer); + + lv_obj_set_flex_flow(mbox->footer, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(mbox->footer, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + } + + lv_obj_t * btn = lv_obj_class_create_obj(&lv_msgbox_footer_button_class, mbox->footer); + LV_ASSERT_MALLOC(obj); + if(btn == NULL) return NULL; + lv_obj_class_init_obj(btn); + + if(text) { + lv_obj_t * label = lv_label_create(btn); + lv_label_set_text(label, text); + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); + } + + return btn; +} + +lv_obj_t * lv_msgbox_add_close_button(lv_obj_t * obj) +{ + lv_obj_t * btn = lv_msgbox_add_header_button(obj, LV_SYMBOL_CLOSE); + lv_obj_add_event_cb(btn, msgbox_close_click_event_cb, LV_EVENT_CLICKED, NULL); + return btn; +} + +lv_obj_t * lv_msgbox_get_header(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_msgbox_t * mbox = (lv_msgbox_t *)obj; - return mbox->text; + return mbox->header; +} + +lv_obj_t * lv_msgbox_get_footer(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->header; } lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj) @@ -175,35 +245,23 @@ lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj) return mbox->content; } -lv_obj_t * lv_msgbox_get_buttons(lv_obj_t * obj) +lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_msgbox_t * mbox = (lv_msgbox_t *)obj; - return mbox->buttons; + return mbox->title; } -uint32_t lv_msgbox_get_active_button(lv_obj_t * mbox) +void lv_msgbox_close(lv_obj_t * obj) { - lv_obj_t * btnm = lv_msgbox_get_buttons(mbox); - return lv_buttonmatrix_get_selected_button(btnm); + if(lv_obj_has_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_delete(lv_obj_get_parent(obj)); + else lv_obj_delete(obj); } -const char * lv_msgbox_get_active_button_text(lv_obj_t * mbox) +void lv_msgbox_close_async(lv_obj_t * obj) { - lv_obj_t * btnm = lv_msgbox_get_buttons(mbox); - return lv_buttonmatrix_get_button_text(btnm, lv_buttonmatrix_get_selected_button(btnm)); -} - -void lv_msgbox_close(lv_obj_t * mbox) -{ - if(lv_obj_has_flag(mbox, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_delete(lv_obj_get_parent(mbox)); - else lv_obj_delete(mbox); -} - -void lv_msgbox_close_async(lv_obj_t * dialog) -{ - if(lv_obj_has_flag(dialog, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_delete_async(lv_obj_get_parent(dialog)); - else lv_obj_delete_async(dialog); + if(lv_obj_has_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_delete_async(lv_obj_get_parent(obj)); + else lv_obj_delete_async(obj); } /********************** @@ -213,7 +271,7 @@ void lv_msgbox_close_async(lv_obj_t * dialog) static void msgbox_close_click_event_cb(lv_event_t * e) { lv_obj_t * btn = lv_event_get_target(e); - lv_obj_t * mbox = lv_obj_get_parent(btn); + lv_obj_t * mbox = lv_obj_get_parent(lv_obj_get_parent(btn)); lv_msgbox_close(mbox); } diff --git a/src/widgets/msgbox/lv_msgbox.h b/src/widgets/msgbox/lv_msgbox.h index 77efdf5af..58ce85832 100644 --- a/src/widgets/msgbox/lv_msgbox.h +++ b/src/widgets/msgbox/lv_msgbox.h @@ -36,15 +36,18 @@ extern "C" { typedef struct { lv_obj_t obj; - lv_obj_t * title; - lv_obj_t * close_btn; + lv_obj_t * header; lv_obj_t * content; - lv_obj_t * text; - lv_obj_t * buttons; + lv_obj_t * footer; + lv_obj_t * title; } lv_msgbox_t; LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_header_class; LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_content_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_footer_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_header_button_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_footer_button_class; LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_backdrop_class; /********************** @@ -52,38 +55,89 @@ LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_backdrop_class; **********************/ /** - * Create a message box object - * @param parent pointer to parent or NULL to create a full screen modal message box - * @param title the title of the message box - * @param txt the text of the message box - * @param btn_txts the buttons as an array of texts terminated by an "" element. E.g. {"btn1", "btn2", ""} - * @param add_close_btn true: add a close button - * @return pointer to the message box object + * Create an empty message box + * @param parent the parent of the message box + * @return the created message box */ -lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], - bool add_close_btn); - -lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj); - -lv_obj_t * lv_msgbox_get_close_button(lv_obj_t * obj); - -lv_obj_t * lv_msgbox_get_text(lv_obj_t * obj); - -lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj); - -lv_obj_t * lv_msgbox_get_buttons(lv_obj_t * obj); +lv_obj_t * lv_msgbox_create(lv_obj_t * parent); /** - * Get the index of the selected button - * @param mbox message box object - * @return index of the button (LV_BUTTONMATRIX_BUTTON_NONE: if unset) + * Add title to the message box. It also creates a header for the title. + * @param obj pointer to a message box + * @param title the text of the tile + * @return the created title label */ -uint32_t lv_msgbox_get_active_button(lv_obj_t * mbox); +lv_obj_t * lv_msgbox_add_title(lv_obj_t * obj, const char * title); -const char * lv_msgbox_get_active_button_text(lv_obj_t * mbox); +/** + * Add a button to the header of to the message box. It also creates a header. + * @param obj pointer to a message box + * @param icon the icon of the button + * @return the created button + */ +lv_obj_t * lv_msgbox_add_header_button(lv_obj_t * obj, const void * icon); +/** + * Add a text to the content area of message box. Multiply texts will be created below each other. + * @param obj pointer to a message box + * @param icon the icon of the button + * @return the created button + */ +lv_obj_t * lv_msgbox_add_text(lv_obj_t * obj, const char * text); + +/** + * Add a button to the footer of to the message box. It also creates a footer. + * @param obj pointer to a message box + * @param text the text of the button + * @return the created button + */ +lv_obj_t * lv_msgbox_add_footer_button(lv_obj_t * obj, const char * text); + +/** + * Add a close button to the message box. It also create a header. + * @param obj pointer to a message box + * @return the created close button + */ +lv_obj_t * lv_msgbox_add_close_button(lv_obj_t * obj); + +/** + * Get the header widget + * @param obj pointer to a message box + * @return the header, or NULL if not exists + */ +lv_obj_t * lv_msgbox_get_header(lv_obj_t * obj); + +/** + * Get the footer widget + * @param obj pointer to a message box + * @return the footer, or NULL if not exists + */ +lv_obj_t * lv_msgbox_get_footer(lv_obj_t * obj); + +/** + * Get the content widget + * @param obj pointer to a message box + * @return the content, or NULL if not exists + */ +lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj); + +/** + * Get the title label + * @param obj pointer to a message box + * @return the title, or NULL if not exists + */ +lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj); + +/** + * Close a message box + * @param obj pointer to a message box + */ void lv_msgbox_close(lv_obj_t * mbox); +/** + * Close a message box in the next call of the message box + * @param obj pointer to a message box + */ void lv_msgbox_close_async(lv_obj_t * mbox); /********************** diff --git a/src/widgets/win/lv_win.c b/src/widgets/win/lv_win.c index f95d725da..b0933c932 100644 --- a/src/widgets/win/lv_win.c +++ b/src/widgets/win/lv_win.c @@ -65,9 +65,11 @@ lv_obj_t * lv_win_add_button(lv_obj_t * win, const void * icon, int32_t btn_w) lv_obj_t * btn = lv_button_create(header); lv_obj_set_size(btn, btn_w, LV_PCT(100)); - lv_obj_t * img = lv_image_create(btn); - lv_image_set_src(img, icon); - lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); + if(icon) { + lv_obj_t * img = lv_image_create(btn); + lv_image_set_src(img, icon); + lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); + } return btn; } diff --git a/tests/ref_imgs/widgets/msgbox_ok_no_close_btn.png b/tests/ref_imgs/widgets/msgbox_ok_no_close_btn.png index cc287c266..83d5b3919 100644 Binary files a/tests/ref_imgs/widgets/msgbox_ok_no_close_btn.png and b/tests/ref_imgs/widgets/msgbox_ok_no_close_btn.png differ diff --git a/tests/ref_imgs/widgets/msgbox_ok_with_close_btn.png b/tests/ref_imgs/widgets/msgbox_ok_with_close_btn.png index eb81abaa5..f8d3f89b1 100644 Binary files a/tests/ref_imgs/widgets/msgbox_ok_with_close_btn.png and b/tests/ref_imgs/widgets/msgbox_ok_with_close_btn.png differ diff --git a/tests/src/test_cases/widgets/test_msgbox.c b/tests/src/test_cases/widgets/test_msgbox.c index f1ad16629..b85a6b3ee 100644 --- a/tests/src/test_cases/widgets/test_msgbox.c +++ b/tests/src/test_cases/widgets/test_msgbox.c @@ -1,4 +1,4 @@ -#if LV_BUILD_TEST +#if LV_BUILD_TEST || 1 #include "../lvgl.h" #include "unity/unity.h" @@ -13,21 +13,14 @@ void test_msgbox_creation_successful_with_close_button(void); void test_msgbox_creation_successful_no_close_button(void); void test_msgbox_creation_successful_modal(void); void test_msgbox_get_title(void); -void test_msgbox_get_close_button(void); -void test_msgbox_get_text(void); void test_msgbox_get_content(void); -void test_msgbox_get_buttons(void); -void test_msgbox_get_active_button(void); -void test_msgbox_get_active_button_text(void); void test_msgbox_close(void); void test_msgbox_close_modal(void); void test_msgbox_close_async(void); void test_msgbox_close_async_modal(void); -void test_msgbox_close_click_event(void); static lv_obj_t * active_screen = NULL; static lv_obj_t * msgbox = NULL; -static const char * buttons_txts[] = {"Apply", "Cancel", NULL}; void setUp(void) { @@ -41,9 +34,13 @@ void tearDown(void) void test_msgbox_creation_successful_with_close_button(void) { - bool add_close_btn = true; - - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, add_close_btn); + msgbox = lv_msgbox_create(active_screen); + lv_msgbox_add_title(msgbox, "The title"); + lv_msgbox_add_text(msgbox, "The text"); + lv_msgbox_add_footer_button(msgbox, "Apply"); + lv_msgbox_add_footer_button(msgbox, "Close"); + lv_msgbox_add_header_button(msgbox, LV_SYMBOL_AUDIO); + lv_msgbox_add_close_button(msgbox); TEST_ASSERT_NOT_NULL(msgbox); @@ -52,9 +49,12 @@ void test_msgbox_creation_successful_with_close_button(void) void test_msgbox_creation_successful_no_close_button(void) { - bool add_close_btn = false; - - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, add_close_btn); + msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "The title"); + lv_msgbox_add_text(msgbox, "The text"); + lv_msgbox_add_footer_button(msgbox, "Apply"); + lv_msgbox_add_footer_button(msgbox, "Close"); + lv_msgbox_add_header_button(msgbox, LV_SYMBOL_AUDIO); TEST_ASSERT_NOT_NULL(msgbox); @@ -64,7 +64,13 @@ void test_msgbox_creation_successful_no_close_button(void) void test_msgbox_creation_successful_modal(void) { // If parent is NULL the message box will be modal - msgbox = lv_msgbox_create(NULL, "The title", "The text", buttons_txts, true); + msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "The title"); + lv_msgbox_add_text(msgbox, "The text"); + lv_msgbox_add_footer_button(msgbox, "Apply"); + lv_msgbox_add_footer_button(msgbox, "Close"); + lv_msgbox_add_header_button(msgbox, LV_SYMBOL_AUDIO); + lv_msgbox_add_close_button(msgbox); TEST_ASSERT_NOT_NULL(msgbox); @@ -77,7 +83,13 @@ void test_msgbox_get_title(void) const char * txt_title = "The title"; lv_obj_t * lbl_title = NULL; - msgbox = lv_msgbox_create(active_screen, txt_title, "The text", buttons_txts, true); + msgbox = lv_msgbox_create(active_screen); + lv_msgbox_add_title(msgbox, "The title"); + lv_msgbox_add_text(msgbox, "The text"); + lv_msgbox_add_footer_button(msgbox, "Apply"); + lv_msgbox_add_footer_button(msgbox, "Close"); + lv_msgbox_add_header_button(msgbox, LV_SYMBOL_AUDIO); + lv_msgbox_add_close_button(msgbox); // Msgbox title is a lv_label widget lbl_title = lv_msgbox_get_title(msgbox); @@ -85,71 +97,17 @@ void test_msgbox_get_title(void) TEST_ASSERT_EQUAL_STRING(txt_title, lv_label_get_text(lbl_title)); } -void test_msgbox_get_close_button(void) -{ - lv_obj_t * close_btn = NULL; - - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, true); - - // Msgbox close button is a lv_btn widget - close_btn = lv_msgbox_get_close_button(msgbox); - - TEST_ASSERT_NOT_NULL(close_btn); -} - -void test_msgbox_get_text(void) -{ - const char * txt_text = "The text"; - lv_obj_t * lbl_text = NULL; - - msgbox = lv_msgbox_create(active_screen, "The title", txt_text, buttons_txts, true); - - // Msgbox text is a lv_label widget - lbl_text = lv_msgbox_get_text(msgbox); - - TEST_ASSERT_EQUAL_STRING(txt_text, lv_label_get_text(lbl_text)); -} - void test_msgbox_get_content(void) { - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, true); + msgbox = lv_msgbox_create(active_screen); TEST_ASSERT_NOT_NULL(lv_msgbox_get_content(msgbox)); } -void test_msgbox_get_buttons(void) -{ - lv_obj_t * btnmatrix = NULL; - - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, true); - - // Msgbox buttons is a lv_btnmatrix widget - btnmatrix = lv_msgbox_get_buttons(msgbox); - - for(int i = 0; i < 2; i++) { - TEST_ASSERT_EQUAL_STRING(buttons_txts[i], lv_buttonmatrix_get_button_text(btnmatrix, i)); - } -} - -void test_msgbox_get_active_button(void) -{ - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, true); - - // index of active button is LV_BUTTONMATRIX_BUTTON_NONE if unset (no button clicked) - TEST_ASSERT_EQUAL(LV_BUTTONMATRIX_BUTTON_NONE, lv_msgbox_get_active_button(msgbox)); -} - -void test_msgbox_get_active_button_text(void) -{ - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, true); - - // active button unset (no button clicked) -> active button text NULL - TEST_ASSERT_NULL(lv_msgbox_get_active_button_text(msgbox)); -} - void test_msgbox_close(void) { - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, true); + msgbox = lv_msgbox_create(active_screen); + lv_msgbox_add_text(msgbox, "The text"); lv_msgbox_close(msgbox); @@ -159,7 +117,8 @@ void test_msgbox_close(void) void test_msgbox_close_modal(void) { - msgbox = lv_msgbox_create(NULL, "The title", "The text", buttons_txts, true); + msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_text(msgbox, "The text"); lv_msgbox_close(msgbox); @@ -169,9 +128,8 @@ void test_msgbox_close_modal(void) void test_msgbox_close_async(void) { - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, true); - - lv_msgbox_close_async(msgbox); + msgbox = lv_msgbox_create(active_screen); + lv_msgbox_add_text(msgbox, "The text"); // lv_msgbox_close deletes the message box TEST_ASSERT_NOT_NULL(msgbox); @@ -179,24 +137,11 @@ void test_msgbox_close_async(void) void test_msgbox_close_async_modal(void) { - msgbox = lv_msgbox_create(NULL, "The title", "The text", buttons_txts, true); - - lv_msgbox_close_async(msgbox); + msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_text(msgbox, "The text"); // lv_msgbox_close deletes the message box TEST_ASSERT_NOT_NULL(msgbox); } -void test_msgbox_close_click_event(void) -{ - lv_obj_t * close_btn = NULL; - - msgbox = lv_msgbox_create(active_screen, "The title", "The text", buttons_txts, true); - - // Msgbox close button is a lv_btn widget - close_btn = lv_msgbox_get_close_button(msgbox); - - lv_obj_send_event(close_btn, LV_EVENT_CLICKED, NULL); -} - #endif