elgerg
March 8, 2022, 5:59pm
1
Description
Using the calendar, is there a way to prevent the user from selecting a date before another date, IE today or another specified date?
IE I want the start to be no earlier than today and the end to be no earlier than the start…
What MCU/Processor/Board and compiler are you using?
Simulator
What LVGL version are you using?
8.1
What do you want to achieve?
As described
What have you tried so far?
Review docs, I cant see anything that would help, maybe this should be a feature request?
Code to reproduce
void cb_setLeavingDate(lv_event_t * event)
{
lv_obj_t * cont = lv_win_get_content(holidy_mode_window); /*Content can be added here*/
lv_obj_t * calendar = lv_calendar_create(cont);
lv_obj_set_size(calendar, 385, 385);
lv_obj_align(calendar, LV_ALIGN_CENTER, 0, 0);
lv_obj_add_event_cb(calendar, cb_calendar_leavingDate, LV_EVENT_ALL, NULL);
lv_calendar_set_today_date(calendar, 2022, 03, 8);
lv_calendar_set_showed_date(calendar, 2022, 03);
/*Highlight a few days*/
static lv_calendar_date_t highlighted_days[1]; /*Only its pointer will be saved so should be static*/
highlighted_days[0].year = 2021;
highlighted_days[0].month = 03;
highlighted_days[0].day = 8;
lv_calendar_set_highlighted_dates(calendar, highlighted_days, 3);
lv_calendar_header_arrow_create(calendar);
lv_calendar_set_showed_date(calendar, 2022, 3);
}
Screenshot and/or video
elgerg
March 12, 2022, 11:10pm
2
@bader given you are totally rocking today do you have any ideas on this one?
Thanks in advance!
bader
March 13, 2022, 12:42am
3
You are more than welcome. Mmm this is interesting, I don’t know if there is such functionality in this library, but I came with my own workaround (Not completed yet).
bool isBeforeToday = true;
static void cb_calendar_event_draw_begin(lv_event_t* e)
{
lv_obj_t* obj = lv_event_get_target(e);
lv_obj_draw_part_dsc_t* dsc = lv_event_get_param(e);
/*Change the draw descriptor*/
if (dsc->id != 0) {
dsc->rect_dsc->radius = 0;
if (lv_btnmatrix_has_btn_ctrl(obj, dsc->id, LV_BTNMATRIX_CTRL_CUSTOM_1)) {
dsc->rect_dsc->border_color = lv_palette_main(LV_PALETTE_RED);
isBeforeToday = false;
}
else if(isBeforeToday) {
lv_btnmatrix_set_btn_ctrl(obj, dsc->id, LV_BTNMATRIX_CTRL_DISABLED);
}
if (dsc->id == 48) {
isBeforeToday = true;
}
}
}
.
lv_obj_t * calendar = lv_calendar_create(cont);
lv_obj_t * btnMatrix= lv_calendar_get_btnmatrix(calendar);
lv_obj_add_event_cb(btnMatrix, cb_calendar_event_draw_begin, LV_EVENT_DRAW_PART_BEGIN, NULL);
The problem here is when you go to the next month, all squares are disabled. I will try to work on it sometime later.
I hope it helps.
elgerg
March 13, 2022, 6:28pm
4
Do you think this would be a useful feature request?
Thanks!
ankit
May 28, 2022, 11:29am
5
hello guys,
Any solution of this problem?
@kisvegabor any chance this can be added as a FR?
Thanks
I can see an elegant solution:
static void prev_event_cb(lv_event_t * e)
{
lv_obj_t * calendar = lv_event_get_user_data(e);
const lv_calendar_date_t * d = lv_calendar_get_showed_date(calendar);
if(d->year <= 2020 && d->month <= 5) {
lv_event_stop_processing(e);
}
}
...
lv_obj_t * header = lv_calendar_header_arrow_create(calendar);
lv_obj_add_event_cb(lv_obj_get_child(header, 0), prev_event_cb, LV_EVENT_CLICKED | LV_EVENT_PREPROCESS, calendar);
It prevents selecting a date before 2021.05.
Hi @kisvegabor
Thanks for looking into this for me.
This solution provides part of what I need as in you cant go back before a specific month. I would however like to prevent the user from selecting a specific date as well.
For example I wouldnt want them to be able to select the 1st to the 7th if the date today is the 8th.
Is that possible?
Thanks
Hi Alex,
Expanding on @kisvegabor 's previous answer:
I would do something like this:
static void prev_event_cb(lv_event_t * e)
{
lv_obj_t * calendar = lv_event_get_user_data(e);
const lv_calendar_date_t * d = lv_calendar_get_showed_date(calendar);
/*pseudo code for obtaining the date & time from your platforms Realtime clock*/
platform_time_struct current_date_time = platform_get_date_time();
if(d->year <= 2020 && d->month <= 5 && d->day < current_date_time.day ) {
lv_event_stop_processing(e);
}
}
...
lv_obj_t * header = lv_calendar_header_arrow_create(calendar);
lv_obj_add_event_cb(lv_obj_get_child(header, 0), prev_event_cb, LV_EVENT_CLICKED | LV_EVENT_PREPROCESS, calendar);
I hope that makes sense, obviously you will need to sort out the pseudo code to obtain the current day from your system clock.
Kind Regards,
Pete
cc: @elgerg , @ankit , @bader
1 Like
ankit
June 9, 2022, 9:55am
10
thanks I will look into it.
Again thanks for providing the infomation!
elgerg
June 9, 2022, 10:22am
11
Hi Pete,
Thanks for the suggestion but I already tried that.
The problem is that the callback processes the header:
Where I want to disable the days as well:
Any suggestions would be welcome!
Thanks
Alex
Hi Alex,
At first glance I think you can combine @bader 's answer with @kisvegabor 's to get your solution. I can’t look at it today but if you can’t work it out repost and I will take a look when I have a little more time.
Cheers,
Pete
elgerg
June 9, 2022, 5:01pm
13
@pete-pjb / @kisvegabor
Ok, I’m close with the following:
static void cb_calendar_event_draw_begin(lv_event_t* e)
{
lv_obj_t* obj = lv_event_get_target(e);
lv_obj_t * calendar = lv_event_get_user_data(e);
lv_obj_draw_part_dsc_t* dsc = lv_event_get_param(e);
const lv_calendar_date_t * d = lv_calendar_get_showed_date(calendar);
time_t now = time(&now);
struct tm tm_today = *localtime(&now);
int year = 1900+tm_today.tm_year;
int mon = 1+tm_today.tm_mon;
/*Change the draw descriptor*/
if (dsc->id != 0) {
dsc->rect_dsc->radius = 0;
if (lv_btnmatrix_has_btn_ctrl(obj, dsc->id, LV_BTNMATRIX_CTRL_CUSTOM_1)) {
dsc->rect_dsc->border_color = lv_color_hex(0x01a2b1);
}
else if(d->year <= year && d->month <= mon && dsc->id < tm_today.tm_mday) {
lv_btnmatrix_set_btn_ctrl(obj, dsc->id, LV_BTNMATRIX_CTRL_DISABLED);
}
}
}
However…
const lv_calendar_date_t * d = lv_calendar_get_showed_date(calendar);
always returned d.day as 1
When I try to use dsc->id I get 1 to 8 then back to 1
The final problem is that this:
lv_btnmatrix_set_btn_ctrl(obj, dsc->id, LV_BTNMATRIX_CTRL_DISABLED);
Doesnt seem to have an effect…
Any idea what things I’m missing?
Thanks
Alex
Hi Alex,
Please try this:
static void cb_calendar_event_draw_begin(lv_event_t* e)
{
lv_obj_t* obj = lv_event_get_target(e);
lv_obj_t * calendar = lv_obj_get_parent( obj );
lv_obj_draw_part_dsc_t* dsc = lv_event_get_param(e);
const lv_calendar_date_t * d = lv_calendar_get_showed_date(calendar);
int btn_day;
time_t now = time(&now);
struct tm tm_today = *localtime(&now);
int year = 1900+tm_today.tm_year;
int mon = 1+tm_today.tm_mon;
/*Change the draw descriptor*/
if (dsc->id > 6) {
btn_day = atoi( lv_btnmatrix_get_btn_text( obj, dsc->id ) );
if((d->year < year || d->month < mon) || ( (d->year == year && d->month == mon) && btn_day < tm_today.tm_mday ) ) {
lv_btnmatrix_set_btn_ctrl(obj, dsc->id, LV_BTNMATRIX_CTRL_DISABLED);
dsc->rect_dsc->bg_opa = LV_OPA_TRANSP;
dsc->rect_dsc->border_opa = LV_OPA_TRANSP;
dsc->label_dsc->color = lv_palette_main(LV_PALETTE_GREY);
}
}
}
Hopefully this is what you are trying to achieve.
Kind Regards,
Pete