diff --git a/docs/widgets/extra/calendar.md b/docs/widgets/extra/calendar.md index 05ce4cfef8..e2ae454a97 100644 --- a/docs/widgets/extra/calendar.md +++ b/docs/widgets/extra/calendar.md @@ -14,7 +14,7 @@ The Calendar object is a classic calendar which can: The Calendar is added to the default group (if it is set). Calendar is an editable object which allow selecting and clicking the dates with encoder navigation too. -To make the Calendar flexible, by default it doesn't show the current year or month. Instead, there are external "headers" that can be attached to the calendar. +To make the Calendar flexible, by default it doesn't show the current year or month. Instead, there are optional "headers" that can be attached to the calendar. ## Parts and Styles The calendar object uses the [Button matrix](/widgets/core/btnmatrix) object under the hood to arrange the days into a matrix. @@ -57,16 +57,17 @@ Learn more about [Keys](/overview/indev). ## Headers +**From v8.1 the header is added directly into the Calendar widget and the API of the headers has been changed. ** + ### Arrow buttons -`lv_calendar_header_arrow_create(parent, calendar, button_size)` creates a header that contains a left and right arrow on the sides and a text with the current year and month between them. +`lv_calendar_header_arrow_create(calendar)` creates a header that contains a left and right arrow on the sides and a text with the current year and month between them. ### Drop-down -`lv_calendar_header_dropdown_create(parent, calendar)` creates a header that contains 2 drop-drown lists: one for the year and another for the month. +`lv_calendar_header_dropdown_create(calendar)` creates a header that contains 2 drop-drown lists: one for the year and another for the month. - ## Example ```eval_rst diff --git a/examples/widgets/calendar/lv_example_calendar_1.c b/examples/widgets/calendar/lv_example_calendar_1.c index bf2aa625ff..e76df2ed7d 100644 --- a/examples/widgets/calendar/lv_example_calendar_1.c +++ b/examples/widgets/calendar/lv_example_calendar_1.c @@ -4,7 +4,7 @@ static void event_handler(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); if(code == LV_EVENT_VALUE_CHANGED) { lv_calendar_date_t date; @@ -41,10 +41,11 @@ void lv_example_calendar_1(void) lv_calendar_set_highlighted_dates(calendar, highlighted_days, 3); #if LV_USE_CALENDAR_HEADER_DROPDOWN - lv_calendar_header_dropdown_create(lv_scr_act(), calendar); + lv_calendar_header_dropdown_create(calendar); #elif LV_USE_CALENDAR_HEADER_ARROW - lv_calendar_header_arrow_create(lv_scr_act(), calendar, 25); + lv_calendar_header_arrow_create(calendar); #endif + lv_calendar_set_showed_date(calendar, 2021, 10); } #endif diff --git a/src/extra/themes/default/lv_theme_default.c b/src/extra/themes/default/lv_theme_default.c index 921c32dbe2..479dba47f7 100644 --- a/src/extra/themes/default/lv_theme_default.c +++ b/src/extra/themes/default/lv_theme_default.c @@ -118,7 +118,7 @@ typedef struct { #endif #if LV_USE_CALENDAR - lv_style_t calendar_bg, calendar_day; + lv_style_t calendar_btnm_bg, calendar_btnm_day, calendar_header; #endif #if LV_USE_COLORWHEEL @@ -489,16 +489,21 @@ static void style_init(void) #endif #if LV_USE_CALENDAR - style_init_reset(&styles->calendar_bg); - lv_style_set_pad_all(&styles->calendar_bg, PAD_SMALL); - lv_style_set_pad_gap(&styles->calendar_bg, PAD_SMALL / 2); - lv_style_set_radius(&styles->calendar_bg, 0); + style_init_reset(&styles->calendar_btnm_bg); + lv_style_set_pad_all(&styles->calendar_btnm_bg, PAD_SMALL); + lv_style_set_pad_gap(&styles->calendar_btnm_bg, PAD_SMALL / 2); - style_init_reset(&styles->calendar_day); - lv_style_set_border_width(&styles->calendar_day, lv_disp_dpx(theme.disp, 1)); - lv_style_set_border_color(&styles->calendar_day, color_grey); - lv_style_set_bg_color(&styles->calendar_day, color_card); - lv_style_set_bg_opa(&styles->calendar_day, LV_OPA_20); + style_init_reset(&styles->calendar_btnm_day); + lv_style_set_border_width(&styles->calendar_btnm_day, lv_disp_dpx(theme.disp, 1)); + lv_style_set_border_color(&styles->calendar_btnm_day, color_grey); + lv_style_set_bg_color(&styles->calendar_btnm_day, color_card); + lv_style_set_bg_opa(&styles->calendar_btnm_day, LV_OPA_20); + + style_init_reset(&styles->calendar_header); + lv_style_set_pad_hor(&styles->calendar_header, PAD_SMALL); + lv_style_set_pad_top(&styles->calendar_header, PAD_SMALL); + lv_style_set_pad_bottom(&styles->calendar_header, PAD_TINY); + lv_style_set_pad_gap(&styles->calendar_header, PAD_SMALL); #endif #if LV_USE_COLORWHEEL @@ -659,6 +664,15 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) return; } #endif + + +#if LV_USE_CALENDAR + else if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { + /*No style*/ + return; + } +#endif + lv_obj_add_style(obj, &styles->card, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); @@ -714,6 +728,20 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) return; } #endif + +#if LV_USE_CALENDAR + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { + lv_obj_add_style(obj, &styles->calendar_btnm_bg, 0); + lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &styles->calendar_btnm_day, LV_PART_ITEMS); + lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); + lv_obj_add_style(obj, &styles->outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &styles->outline_secondary, LV_PART_ITEMS | LV_STATE_EDITED); + return; + } +#endif lv_obj_add_style(obj, &styles->card, 0); lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); @@ -901,26 +929,19 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_CALENDAR else if(lv_obj_check_type(obj, &lv_calendar_class)) { lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->calendar_bg, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->calendar_day, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_PART_ITEMS | LV_STATE_EDITED); + lv_obj_add_style(obj, &styles->pad_zero, 0); } #endif #if LV_USE_CALENDAR_HEADER_ARROW else if(lv_obj_check_type(obj, &lv_calendar_header_arrow_class)) { - lv_obj_add_style(obj, &styles->card, 0); + lv_obj_add_style(obj, &styles->calendar_header, 0); } #endif #if LV_USE_CALENDAR_HEADER_DROPDOWN else if(lv_obj_check_type(obj, &lv_calendar_header_dropdown_class)) { - lv_obj_add_style(obj, &styles->card, 0); + lv_obj_add_style(obj, &styles->calendar_header, 0); } #endif diff --git a/src/extra/widgets/calendar/lv_calendar.c b/src/extra/widgets/calendar/lv_calendar.c index 8e25247cec..3ba73ea30a 100644 --- a/src/extra/widgets/calendar/lv_calendar.c +++ b/src/extra/widgets/calendar/lv_calendar.c @@ -44,10 +44,9 @@ const lv_obj_class_t lv_calendar_class = { .height_def = (LV_DPI_DEF * 3) / 2, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, .instance_size = sizeof(lv_calendar_t), - .base_class = &lv_btnmatrix_class + .base_class = &lv_obj_class }; - static const char * day_names_def[7] = LV_CALENDAR_DEFAULT_DAY_NAMES; /********************** @@ -79,6 +78,7 @@ void lv_calendar_set_day_names(lv_obj_t * obj, const char * day_names[]) for(i = 0; i < 7; i++) { calendar->map[i] = day_names[i]; } + lv_obj_invalidate(obj); } void lv_calendar_set_today_date(lv_obj_t * obj, uint32_t year, uint32_t month, uint32_t day) @@ -123,9 +123,9 @@ void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month) uint8_t i; /*Remove the disabled state but revert it for day names*/ - lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_DISABLED); + lv_btnmatrix_clear_btn_ctrl_all(calendar->btnm, LV_BTNMATRIX_CTRL_DISABLED); for(i = 0; i < 7; i++) { - lv_btnmatrix_set_btn_ctrl(obj, i, LV_BTNMATRIX_CTRL_DISABLED); + lv_btnmatrix_set_btn_ctrl(calendar->btnm, i, LV_BTNMATRIX_CTRL_DISABLED); } uint8_t act_mo_len = get_month_length(d.year, d.month); @@ -138,33 +138,44 @@ void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month) uint8_t prev_mo_len = get_month_length(d.year, d.month - 1); for(i = 0, c = prev_mo_len - day_first + 1; i < day_first; i++, c++) { lv_snprintf(calendar->nums[i], sizeof(calendar->nums[0]), "%d", c); - lv_btnmatrix_set_btn_ctrl(obj, i + 7, LV_BTNMATRIX_CTRL_DISABLED); + lv_btnmatrix_set_btn_ctrl(calendar->btnm, i + 7, LV_BTNMATRIX_CTRL_DISABLED); } for(i = day_first + act_mo_len, c = 1; i < 6 * 7; i++, c++) { lv_snprintf(calendar->nums[i], sizeof(calendar->nums[0]), "%d", c); - lv_btnmatrix_set_btn_ctrl(obj, i + 7, LV_BTNMATRIX_CTRL_DISABLED); + lv_btnmatrix_set_btn_ctrl(calendar->btnm, i + 7, LV_BTNMATRIX_CTRL_DISABLED); } highlight_update(obj); /*Reset the focused button if the days changes*/ - if(lv_btnmatrix_get_selected_btn(obj) != LV_BTNMATRIX_BTN_NONE) { - lv_btnmatrix_set_selected_btn(obj, day_first + 7); + if(lv_btnmatrix_get_selected_btn(calendar->btnm) != LV_BTNMATRIX_BTN_NONE) { + lv_btnmatrix_set_selected_btn(calendar->btnm, day_first + 7); } lv_obj_invalidate(obj); + + /* The children of the calendar are probably headers. + * Notify them to let the headers updated to the new date*/ + uint32_t child_cnt = lv_obj_get_child_cnt(obj); + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); + if(child == calendar->btnm) continue; + lv_event_send(child, LV_EVENT_VALUE_CHANGED, obj); + } } /*===================== * Getter functions *====================*/ -/** - * Get the today's date - * @param calendar pointer to a calendar object - * @return return pointer to an `lv_calendar_date_t` variable containing the date of today. - */ +lv_obj_t * lv_calendar_get_btnmatrix(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + const lv_calendar_t * calendar = (lv_calendar_t *)obj; + return calendar->btnm; +} + const lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -173,11 +184,6 @@ const lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * obj) return &calendar->today; } -/** - * Get the currently showed - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` variable containing the date is being shown. - */ const lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -186,11 +192,6 @@ const lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * obj) return &calendar->showed_date; } -/** - * Get the the highlighted dates - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` array containing the dates. - */ lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -212,7 +213,7 @@ lv_res_t lv_calendar_get_pressed_date(const lv_obj_t * obj, lv_calendar_date_t * LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; - uint16_t d = lv_btnmatrix_get_selected_btn(obj); + uint16_t d = lv_btnmatrix_get_selected_btn(calendar->btnm); if(d == LV_BTNMATRIX_BTN_NONE) { date->year = 0; date->month = 0; @@ -220,7 +221,7 @@ lv_res_t lv_calendar_get_pressed_date(const lv_obj_t * obj, lv_calendar_date_t * return LV_RES_INV; } - const char * txt = lv_btnmatrix_get_btn_text(obj, lv_btnmatrix_get_selected_btn(obj)); + const char * txt = lv_btnmatrix_get_btn_text(calendar->btnm, lv_btnmatrix_get_selected_btn(calendar->btnm)); if(txt[1] == 0) date->day = txt[0] - '0'; else date->day = (txt[0] - '0') * 10 + (txt[1] - '0'); @@ -272,14 +273,19 @@ static void lv_calendar_constructor(const lv_obj_class_t * class_p, lv_obj_t * o } calendar->map[8 * 7 - 1] = ""; - lv_btnmatrix_set_map(obj, calendar->map); - lv_btnmatrix_set_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); + calendar->btnm = lv_btnmatrix_create(obj); + lv_btnmatrix_set_map(calendar->btnm, calendar->map); + lv_btnmatrix_set_btn_ctrl_all(calendar->btnm, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); + lv_obj_add_event_cb(calendar->btnm, draw_part_begin_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); + lv_obj_set_width(calendar->btnm, lv_pct(100)); + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_grow(calendar->btnm, 1); lv_calendar_set_showed_date(obj, calendar->showed_date.year, calendar->showed_date.month); lv_calendar_set_today_date(obj, calendar->today.year, calendar->today.month, calendar->today.day); - lv_obj_add_event_cb(obj, draw_part_begin_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); + lv_obj_add_flag(calendar->btnm, LV_OBJ_FLAG_EVENT_BUBBLE); } static void draw_part_begin_event_cb(lv_event_t * e) @@ -315,9 +321,6 @@ static void draw_part_begin_event_cb(lv_event_t * e) } } - - - /** * Get the number of days in a month * @param year a year @@ -378,20 +381,20 @@ static void highlight_update(lv_obj_t * obj) uint16_t i; /*Clear all kind of selection*/ - lv_btnmatrix_clear_btn_ctrl_all(obj, LV_CALENDAR_CTRL_TODAY | LV_CALENDAR_CTRL_HIGHLIGHT); + lv_btnmatrix_clear_btn_ctrl_all(calendar->btnm, LV_CALENDAR_CTRL_TODAY | LV_CALENDAR_CTRL_HIGHLIGHT); uint8_t day_first = get_day_of_week(calendar->showed_date.year, calendar->showed_date.month, 1); if(calendar->highlighted_dates) { for(i = 0; i < calendar->highlighted_dates_num; i++) { if(calendar->highlighted_dates[i].year == calendar->showed_date.year && calendar->highlighted_dates[i].month == calendar->showed_date.month) { - lv_btnmatrix_set_btn_ctrl(obj, calendar->highlighted_dates[i].day - 1 + day_first + 7, LV_CALENDAR_CTRL_HIGHLIGHT); + lv_btnmatrix_set_btn_ctrl(calendar->btnm, calendar->highlighted_dates[i].day - 1 + day_first + 7, LV_CALENDAR_CTRL_HIGHLIGHT); } } } if(calendar->showed_date.year == calendar->today.year && calendar->showed_date.month == calendar->today.month) { - lv_btnmatrix_set_btn_ctrl(obj, calendar->today.day - 1 + day_first + 7, LV_CALENDAR_CTRL_TODAY); + lv_btnmatrix_set_btn_ctrl(calendar->btnm, calendar->today.day - 1 + day_first + 7, LV_CALENDAR_CTRL_TODAY); } } diff --git a/src/extra/widgets/calendar/lv_calendar.h b/src/extra/widgets/calendar/lv_calendar.h index 89cee96379..afda7ab92b 100644 --- a/src/extra/widgets/calendar/lv_calendar.h +++ b/src/extra/widgets/calendar/lv_calendar.h @@ -36,7 +36,8 @@ typedef struct { /*Data of calendar*/ typedef struct { - lv_btnmatrix_t btnm; + lv_obj_t obj; + lv_obj_t * btnm; /*New data for this type*/ lv_calendar_date_t today; /*Date of today*/ lv_calendar_date_t showed_date; /*Currently visible month (day is ignored)*/ @@ -102,6 +103,22 @@ void lv_calendar_set_day_names(lv_obj_t * obj, const char ** day_names); * Getter functions *====================*/ +/** + * Get the header object of the calendar. + * Date selectors can be created here + * @param obj pointer to a calendar object + * @return pointer to a container (lv_obj) for a header + */ +lv_obj_t * lv_calendar_get_header(const lv_obj_t * obj); + +/** + * Get the button matrix object of the calendar. + * It shows the dates and day names. + * @param obj pointer to a calendar object + * @return pointer to a the button matrix + */ +lv_obj_t * lv_calendar_get_btnmatrix(const lv_obj_t * obj); + /** * Get the today's date * @param calendar pointer to a calendar object diff --git a/src/extra/widgets/calendar/lv_calendar_header_arrow.c b/src/extra/widgets/calendar/lv_calendar_header_arrow.c index 890ce49d87..fecb1392e7 100644 --- a/src/extra/widgets/calendar/lv_calendar_header_arrow.c +++ b/src/extra/widgets/calendar/lv_calendar_header_arrow.c @@ -27,18 +27,19 @@ **********************/ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void month_event_cb(lv_event_t * e); +static void value_changed_event_cb(lv_event_t * e); /********************** * STATIC VARIABLES **********************/ const lv_obj_class_t lv_calendar_header_arrow_class = { .base_class = &lv_obj_class, - .constructor_cb = my_constructor + .constructor_cb = my_constructor, + .width_def = LV_PCT(100), + .height_def = LV_DPI_DEF / 3 }; static const char * month_names_def[12] = LV_CALENDAR_DEFAULT_MONTH_NAMES; -static lv_obj_t * calendar_param; -static lv_coord_t btn_size_param; /********************** * MACROS @@ -48,10 +49,8 @@ static lv_coord_t btn_size_param; * GLOBAL FUNCTIONS **********************/ -lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent, lv_obj_t * calendar, lv_coord_t btn_size) +lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent) { - calendar_param = calendar; - btn_size_param = btn_size; lv_obj_t * obj = lv_obj_class_create_obj(&lv_calendar_header_arrow_class, parent); lv_obj_class_init_obj(obj); return obj; @@ -67,41 +66,36 @@ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) LV_UNUSED(class_p); - /*Use the same paddings as the calendar_param*/ - lv_obj_set_style_pad_left(obj, lv_obj_get_style_pad_left(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_right(obj, lv_obj_get_style_pad_right(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_top(obj, lv_obj_get_style_pad_top(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_bottom(obj, lv_obj_get_style_pad_bottom(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_column(obj, lv_obj_get_style_pad_column(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_radius(obj, lv_obj_get_style_radius(calendar_param, LV_PART_MAIN), 0); + lv_obj_move_to_index(obj, 0); - const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar_param); - - lv_obj_update_layout(calendar_param); - lv_coord_t w = lv_obj_get_width(calendar_param); - lv_obj_set_size(obj, w, LV_SIZE_CONTENT); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(obj, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START); lv_obj_t * mo_prev = lv_btn_create(obj); lv_obj_set_style_bg_img_src(mo_prev, LV_SYMBOL_LEFT, 0); - lv_obj_set_size(mo_prev, btn_size_param, btn_size_param); - lv_obj_add_event_cb(mo_prev, month_event_cb, LV_EVENT_CLICKED, calendar_param); + lv_obj_set_height(mo_prev, lv_pct(100)); + lv_obj_update_layout(mo_prev); + lv_coord_t btn_size = lv_obj_get_height(mo_prev); + lv_obj_set_width(mo_prev, btn_size); + + lv_obj_add_event_cb(mo_prev, month_event_cb, LV_EVENT_CLICKED, NULL); lv_obj_clear_flag(mo_prev, LV_OBJ_FLAG_CLICK_FOCUSABLE); lv_obj_t * label = lv_label_create(obj); lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_flex_grow(label, 1); - lv_label_set_text_fmt(label, "%d %s", cur_date->year, month_names_def[cur_date->month - 1]); lv_obj_t * mo_next = lv_btn_create(obj); lv_obj_set_style_bg_img_src(mo_next, LV_SYMBOL_RIGHT, 0); - lv_obj_set_size(mo_next, btn_size_param, btn_size_param); - lv_obj_add_event_cb(mo_next, month_event_cb, LV_EVENT_CLICKED, calendar_param); + lv_obj_set_size(mo_next, btn_size, btn_size); + + lv_obj_add_event_cb(mo_next, month_event_cb, LV_EVENT_CLICKED, NULL); lv_obj_clear_flag(mo_next, LV_OBJ_FLAG_CLICK_FOCUSABLE); - lv_obj_align_to(obj, calendar_param, LV_ALIGN_OUT_TOP_MID, 0, 0); + lv_obj_add_event_cb(obj, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL); + /*Refresh the drop downs*/ + lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); } static void month_event_cb(lv_event_t * e) @@ -109,7 +103,7 @@ static void month_event_cb(lv_event_t * e) lv_obj_t * btn = lv_event_get_target(e); lv_obj_t * header = lv_obj_get_parent(btn); - lv_obj_t * calendar = lv_event_get_user_data(e); + lv_obj_t * calendar = lv_obj_get_parent(header); const lv_calendar_date_t * d; d = lv_calendar_get_showed_date(calendar); @@ -141,5 +135,15 @@ static void month_event_cb(lv_event_t * e) lv_label_set_text_fmt(label, "%d %s", newd.year, month_names_def[newd.month - 1]); } +static void value_changed_event_cb(lv_event_t * e) +{ + lv_obj_t * header = lv_event_get_target(e); + lv_obj_t * calendar = lv_obj_get_parent(header); + + const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar); + lv_obj_t * label = lv_obj_get_child(header, 1); + lv_label_set_text_fmt(label, "%d %s", cur_date->year, month_names_def[cur_date->month - 1]); +} + #endif /*LV_USE_CALENDAR_HEADER_ARROW*/ diff --git a/src/extra/widgets/calendar/lv_calendar_header_arrow.h b/src/extra/widgets/calendar/lv_calendar_header_arrow.h index b4e3b52e3e..f33ef7dc8d 100644 --- a/src/extra/widgets/calendar/lv_calendar_header_arrow.h +++ b/src/extra/widgets/calendar/lv_calendar_header_arrow.h @@ -30,11 +30,11 @@ extern const lv_obj_class_t lv_calendar_header_arrow_class; **********************/ /** - * Create a calendar objects - * @param par pointer to an object, it will be the parent of the new calendar - * @return pointer to the created calendar + * Create a calendar header with drop-drowns to select the year and month + * @param parent pointer to a calendar object. + * @return the created header */ -lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent, lv_obj_t * calendar, lv_coord_t btn_size); +lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent); /********************** * MACROS diff --git a/src/extra/widgets/calendar/lv_calendar_header_dropdown.c b/src/extra/widgets/calendar/lv_calendar_header_dropdown.c index 41d30445c4..5e8f90d4a7 100644 --- a/src/extra/widgets/calendar/lv_calendar_header_dropdown.c +++ b/src/extra/widgets/calendar/lv_calendar_header_dropdown.c @@ -27,12 +27,15 @@ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void year_event_cb(lv_event_t * e); static void month_event_cb(lv_event_t * e); +static void value_changed_event_cb(lv_event_t * e); /********************** * STATIC VARIABLES **********************/ const lv_obj_class_t lv_calendar_header_dropdown_class = { .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_SIZE_CONTENT, .constructor_cb = my_constructor }; @@ -47,8 +50,6 @@ static const char * year_list = { "1920\n1919\n1918\n1917\n1916\n1915\n1914\n1913\n1912\n1911\n1910\n1909\n1908\n1907\n1906\n1905\n1904\n1903\n1902\n1901" }; -static lv_obj_t * calendar_param; - /********************** * MACROS **********************/ @@ -57,9 +58,8 @@ static lv_obj_t * calendar_param; * GLOBAL FUNCTIONS **********************/ -lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent, lv_obj_t * calendar) +lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent) { - calendar_param = calendar; lv_obj_t * obj = lv_obj_class_create_obj(&lv_calendar_header_dropdown_class, parent); lv_obj_class_init_obj(obj); @@ -76,36 +76,23 @@ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) LV_UNUSED(class_p); - /*Use the same paddings as the calendar_param*/ - lv_obj_set_style_pad_left(obj, lv_obj_get_style_pad_left(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_right(obj, lv_obj_get_style_pad_right(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_top(obj, lv_obj_get_style_pad_top(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_bottom(obj, lv_obj_get_style_pad_bottom(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_pad_column(obj, lv_obj_get_style_pad_column(calendar_param, LV_PART_MAIN), 0); - lv_obj_set_style_radius(obj, lv_obj_get_style_radius(calendar_param, LV_PART_MAIN), 0); - - const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar_param); - - lv_obj_update_layout(calendar_param); - lv_coord_t w = lv_obj_get_width(calendar_param); - lv_obj_set_size(obj, w, LV_SIZE_CONTENT); + lv_obj_t * calendar = lv_obj_get_parent(obj); + lv_obj_move_to_index(obj, 0); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); - lv_obj_set_flex_align(obj, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START); lv_obj_t * year_dd = lv_dropdown_create(obj); lv_dropdown_set_options(year_dd, year_list); - lv_dropdown_set_selected(year_dd, 2023 - cur_date->year); - lv_obj_add_event_cb(year_dd, year_event_cb, LV_EVENT_VALUE_CHANGED, calendar_param); + lv_obj_add_event_cb(year_dd, year_event_cb, LV_EVENT_VALUE_CHANGED, calendar); lv_obj_set_flex_grow(year_dd, 1); lv_obj_t * month_dd = lv_dropdown_create(obj); lv_dropdown_set_options(month_dd, month_list); - lv_dropdown_set_selected(month_dd, cur_date->month - 1); - lv_obj_add_event_cb(month_dd, month_event_cb, LV_EVENT_VALUE_CHANGED, calendar_param); + lv_obj_add_event_cb(month_dd, month_event_cb, LV_EVENT_VALUE_CHANGED, calendar); lv_obj_set_flex_grow(month_dd, 1); - lv_obj_align_to(obj, calendar_param, LV_ALIGN_OUT_TOP_MID, 0, 0); - + lv_obj_add_event_cb(obj, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL); + /*Refresh the drop downs*/ + lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); } static void month_event_cb(lv_event_t * e) @@ -122,6 +109,7 @@ static void month_event_cb(lv_event_t * e) lv_calendar_set_showed_date(calendar, newd.year, newd.month); } + static void year_event_cb(lv_event_t * e) { lv_obj_t * dropdown = lv_event_get_target(e); @@ -137,5 +125,18 @@ static void year_event_cb(lv_event_t * e) lv_calendar_set_showed_date(calendar, newd.year, newd.month); } +static void value_changed_event_cb(lv_event_t * e) +{ + lv_obj_t * header = lv_event_get_target(e); + lv_obj_t * calendar = lv_obj_get_parent(header); + const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar); + + lv_obj_t * year_dd = lv_obj_get_child(header, 0); + lv_dropdown_set_selected(year_dd, 2023 - cur_date->year); + + lv_obj_t * month_dd = lv_obj_get_child(header, 1); + lv_dropdown_set_selected(month_dd, cur_date->month - 1); +} + #endif /*LV_USE_CALENDAR_HEADER_ARROW*/ diff --git a/src/extra/widgets/calendar/lv_calendar_header_dropdown.h b/src/extra/widgets/calendar/lv_calendar_header_dropdown.h index 8d6333d9d2..7ce924e941 100644 --- a/src/extra/widgets/calendar/lv_calendar_header_dropdown.h +++ b/src/extra/widgets/calendar/lv_calendar_header_dropdown.h @@ -30,11 +30,11 @@ extern const lv_obj_class_t lv_calendar_header_dropdown_class; **********************/ /** - * Create a calendar objects - * @param par pointer to an object, it will be the parent of the new calendar - * @return pointer to the created calendar + * Create a calendar header with drop-drowns to select the year and month + * @param parent pointer to a calendar object. + * @return the created header */ -lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent, lv_obj_t * calendar); +lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent); /********************** * MACROS diff --git a/src/widgets/lv_label.c b/src/widgets/lv_label.c index f9573473d8..434b8d5c8c 100644 --- a/src/widgets/lv_label.c +++ b/src/widgets/lv_label.c @@ -858,7 +858,11 @@ static void draw_main(lv_event_t * e) txt_coords.y2 = obj->coords.y2; } - lv_draw_label(&txt_coords, clip_area, &label_draw_dsc, label->text, hint); + if(label->long_mode == LV_LABEL_LONG_SCROLL || label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { + lv_draw_label(&txt_coords, &txt_clip, &label_draw_dsc, label->text, hint); + } else { + lv_draw_label(&txt_coords, clip_area, &label_draw_dsc, label->text, hint); + } if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { lv_point_t size; @@ -871,7 +875,7 @@ static void draw_main(lv_event_t * e) lv_font_get_glyph_width(label_draw_dsc.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; label_draw_dsc.ofs_y = label->offset.y; - lv_draw_label(&txt_coords, clip_area, &label_draw_dsc, label->text, hint); + lv_draw_label(&txt_coords, &txt_clip, &label_draw_dsc, label->text, hint); } /*Draw the text again below the original to make a circular effect */ @@ -879,7 +883,7 @@ static void draw_main(lv_event_t * e) label_draw_dsc.ofs_x = label->offset.x; label_draw_dsc.ofs_y = label->offset.y + size.y + lv_font_get_line_height(label_draw_dsc.font); - lv_draw_label(&txt_coords, clip_area, &label_draw_dsc, label->text, hint); + lv_draw_label(&txt_coords, &txt_clip, &label_draw_dsc, label->text, hint); } } }