From 3f76638b37ac8ebf715782512c3c36308cf70a62 Mon Sep 17 00:00:00 2001 From: JEONGHYUN YUN Date: Thu, 17 Nov 2016 16:39:42 -0800 Subject: [PATCH] elm/calendar: add APIs for minimum and maximum values for the date Summary: elm_calendar already have minimum and maximum year set/get APIs. I've added new APIs that exapanded from the year to the date. These APIs help us not only set min/max month but also set min/max day. If you set the minimum date, changing the displayed month or year if needed. Displayed day also to be disabled if it is smaller than minimum date. Reviewers: woohyun, Hermet, jpeg, CHAN, cedric Reviewed By: CHAN, cedric Subscribers: CHAN, cedric, jpeg Differential Revision: https://phab.enlightenment.org/D4226 Signed-off-by: Cedric Bail --- src/bin/elementary/test_calendar.c | 22 +- src/lib/elementary/elm_calendar.c | 251 ++++++++++++++++++++--- src/lib/elementary/elm_calendar.eo | 76 ++++--- src/lib/elementary/elm_calendar_legacy.h | 30 +++ src/lib/elementary/elm_widget_calendar.h | 4 +- 5 files changed, 319 insertions(+), 64 deletions(-) diff --git a/src/bin/elementary/test_calendar.c b/src/bin/elementary/test_calendar.c index 6f3eb5685d..35e1bf95a6 100644 --- a/src/bin/elementary/test_calendar.c +++ b/src/bin/elementary/test_calendar.c @@ -38,7 +38,6 @@ set_api_state(api_data *api) { Evas_Object *cal = eina_list_nth(items, 0); time_t the_time = (SEC_PER_YEAR * 41) + (SEC_PER_DAY * 9); /* Set date to DEC 31, 2010 */ - elm_calendar_min_max_year_set(cal, 2010, 2011); m = elm_calendar_mark_add(cal, "checked", gmtime(&the_time), ELM_CALENDAR_MONTHLY); elm_calendar_selected_time_set(cal, gmtime(&the_time)); } @@ -143,7 +142,6 @@ test_calendar(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_ time_t the_time = (SEC_PER_YEAR * 41) + (SEC_PER_DAY * 9); /* Set date to DEC 31, 2010 */ elm_calendar_selected_time_set(cal, gmtime(&the_time)); - elm_calendar_min_max_year_set(cal, 2010, 2012); evas_object_show(cal); @@ -155,25 +153,30 @@ _print_cal_info(Evas_Object *cal, Evas_Object *en) { char info[1024]; double interval; - int year_min, year_max; Eina_Bool sel_enabled; const char **wds; struct tm stm; + const struct tm *mintm, *maxtm; if (!elm_calendar_selected_time_get(cal, &stm)) return; interval = elm_calendar_interval_get(cal); - elm_calendar_min_max_year_get(cal, &year_min, &year_max); + mintm = elm_calendar_date_min_get(cal); + maxtm = elm_calendar_date_max_get(cal); sel_enabled = !!(elm_calendar_select_mode_get(cal) != ELM_CALENDAR_SELECT_MODE_NONE); wds = elm_calendar_weekdays_names_get(cal); snprintf(info, sizeof(info), " Day: %i, Mon: %i, Year %i, WeekDay: %i
" - " Interval: %0.2f, Year_Min: %i, Year_Max %i, Sel Enabled : %i
" + " Interval: %0.2f, Sel Enabled : %i
" + " Day_Min : %i, Mon_Min : %i, Year_Min : %i
" + " Day_Max : %i, Mon_Max : %i, Year_Max : %i
" " Weekdays: %s, %s, %s, %s, %s, %s, %s
", stm.tm_mday, stm.tm_mon, stm.tm_year + 1900, stm.tm_wday, - interval, year_min, year_max, sel_enabled, + interval, sel_enabled, + mintm->tm_mday, mintm->tm_mon + 1, mintm->tm_year + 1900, + maxtm->tm_mday, maxtm->tm_mon + 1, maxtm->tm_year + 1900, wds[0], wds[1], wds[2], wds[3], wds[4], wds[5], wds[6]); elm_object_text_set(en, info); @@ -231,7 +234,11 @@ _calendar_create(Evas_Object *parent) elm_calendar_first_day_of_week_set(cal, ELM_DAY_SATURDAY); elm_calendar_interval_set(cal, 0.4); elm_calendar_format_function_set(cal, _format_month_year); - elm_calendar_min_max_year_set(cal, 2010, 2020); + + time_t the_time = (SEC_PER_YEAR * 40) + (SEC_PER_DAY * 24); /* Set min date to JAN 15, 2010 */ + elm_calendar_date_min_set(cal, gmtime(&the_time)); + the_time = (SEC_PER_YEAR * 42) + (SEC_PER_DAY * 3); /* Set max date to DEC 25, 2011 */ + elm_calendar_date_max_set(cal, gmtime(&the_time)); current_time = time(NULL) + 4 * SEC_PER_DAY; localtime_r(¤t_time, &selected_time); @@ -327,7 +334,6 @@ test_calendar2(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event elm_calendar_marks_draw(cal3); evas_object_show(cal3); elm_box_pack_end(bxh, cal3); - elm_calendar_min_max_year_set(cal3, -1, -1); evas_object_show(win); } diff --git a/src/lib/elementary/elm_calendar.c b/src/lib/elementary/elm_calendar.c index 1d2a514295..587f9935b0 100644 --- a/src/lib/elementary/elm_calendar.c +++ b/src/lib/elementary/elm_calendar.c @@ -287,6 +287,17 @@ _cit_mark(Evas_Object *cal, int cit, const char *mtype) { + ELM_CALENDAR_DATA_GET(cal, sd); + + int day = cit - sd->first_day_it + 1; + int mon = sd->shown_time.tm_mon; + int yr = sd->shown_time.tm_year; + + if (strcmp(mtype, "clear") + && (((yr == sd->date_min.tm_year) && (mon == sd->date_min.tm_mon) && (day < sd->date_min.tm_mday)) + || ((yr == sd->date_max.tm_year) && (mon == sd->date_max.tm_mon) && (day > sd->date_max.tm_mday)))) + return; + char sign[64]; snprintf(sign, sizeof(sign), "cit_%i,%s", cit, mtype); @@ -575,7 +586,12 @@ _populate(Evas_Object *obj) if ((day) && (day <= maxdays)) { - _enable(sd, i); + if (((yr == sd->date_min.tm_year) && (mon == sd->date_min.tm_mon) && (day < sd->date_min.tm_mday)) + || ((yr == sd->date_max.tm_year) && (mon == sd->date_max.tm_mon) && (day > sd->date_max.tm_mday))) + _disable(sd, i); + else + _enable(sd, i); + snprintf(day_s, sizeof(day_s), "%i", day++); } else @@ -885,6 +901,20 @@ _fix_selected_time(Elm_Calendar_Data *sd) sd->selected_time.tm_mon = sd->shown_time.tm_mon; if (sd->selected_time.tm_year != sd->shown_time.tm_year) sd->selected_time.tm_year = sd->shown_time.tm_year; + + if ((sd->selected_time.tm_year == sd->date_min.tm_year) + && (sd->selected_time.tm_mon == sd->date_min.tm_mon) + && (sd->selected_time.tm_mday < sd->date_min.tm_mday)) + { + sd->selected_time.tm_mday = sd->date_min.tm_mday; + } + else if ((sd->selected_time.tm_year == sd->date_max.tm_year) + && (sd->selected_time.tm_mon == sd->date_max.tm_mon) + && (sd->selected_time.tm_mday > sd->date_max.tm_mday)) + { + sd->selected_time.tm_mday = sd->date_max.tm_mday; + } + mktime(&sd->selected_time); } @@ -909,35 +939,55 @@ _update_data(Evas_Object *obj, Eina_Bool month, if (month) { sd->shown_time.tm_mon += delta; - if (sd->shown_time.tm_mon < 0) + if (delta < 0) { - if (sd->shown_time.tm_year == sd->year_min) + if (sd->shown_time.tm_year == sd->date_min.tm_year) { - sd->shown_time.tm_mon++; - return EINA_FALSE; + if (sd->shown_time.tm_mon < sd->date_min.tm_mon) + { + sd->shown_time.tm_mon = sd->date_min.tm_mon; + return EINA_FALSE; + } + } + else if (sd->shown_time.tm_mon < 0) + { + sd->shown_time.tm_mon = 11; + sd->shown_time.tm_year--; } - sd->shown_time.tm_mon = 11; - sd->shown_time.tm_year--; } - else if (sd->shown_time.tm_mon > 11) + else { - if (sd->shown_time.tm_year == sd->year_max) + if (sd->shown_time.tm_year == sd->date_max.tm_year) { - sd->shown_time.tm_mon--; - return EINA_FALSE; + if (sd->shown_time.tm_mon > sd->date_max.tm_mon) + { + sd->shown_time.tm_mon = sd->date_max.tm_mon; + return EINA_FALSE; + } + } + else if (sd->shown_time.tm_mon > 11) + { + sd->shown_time.tm_mon = 0; + sd->shown_time.tm_year++; } - sd->shown_time.tm_mon = 0; - sd->shown_time.tm_year++; } } else { years = sd->shown_time.tm_year + delta; - if (((years > sd->year_max) && (sd->year_max != -1)) || - years < sd->year_min) + if (((years > sd->date_max.tm_year) && (sd->date_max.tm_year != -1)) || + years < sd->date_min.tm_year) return EINA_FALSE; sd->shown_time.tm_year = years; + if ((years == sd->date_min.tm_year) && (sd->shown_time.tm_mon < sd->date_min.tm_mon)) + { + sd->shown_time.tm_mon = sd->date_min.tm_mon; + } + else if ((years == sd->date_max.tm_year) && (sd->shown_time.tm_mon > sd->date_max.tm_mon)) + { + sd->shown_time.tm_mon = sd->date_max.tm_mon; + } } if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND) @@ -1209,6 +1259,19 @@ _get_item_day(Evas_Object *obj, if ((day < 0) || (day > _maxdays_get(&sd->shown_time, 0))) return 0; + if ((sd->shown_time.tm_year == sd->date_min.tm_year) + && (sd->shown_time.tm_mon == sd->date_min.tm_mon) + && (day < sd->date_min.tm_mday)) + { + return 0; + } + else if ((sd->shown_time.tm_year == sd->date_max.tm_year) + && (sd->shown_time.tm_mon == sd->date_max.tm_mon) + && (day > sd->date_max.tm_mday)) + { + return 0; + } + return day; } @@ -1394,8 +1457,12 @@ _elm_calendar_efl_canvas_group_group_add(Eo *obj, Elm_Calendar_Data *priv) elm_widget_sub_object_parent_add(obj); priv->first_interval = 0.85; - priv->year_min = 2; - priv->year_max = -1; + priv->date_min.tm_year = 2; + priv->date_min.tm_mon = 0; + priv->date_min.tm_mday = 1; + priv->date_max.tm_year = -1; + priv->date_max.tm_mon = 11; + priv->date_max.tm_mday = 31; priv->today_it = -1; priv->selected_it = -1; priv->first_day_it = -1; @@ -1647,29 +1714,153 @@ _elm_calendar_interval_get(Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd) return sd->first_interval; } -EOLIAN static void +EAPI void _elm_calendar_min_max_year_set(Eo *obj, Elm_Calendar_Data *sd, int min, int max) { min -= 1900; max -= 1900; - if ((sd->year_min == min) && (sd->year_max == max)) return; - sd->year_min = min > 2 ? min : 2; - if (max > sd->year_min) - sd->year_max = max; + if ((sd->date_min.tm_year == min) && (sd->date_max.tm_year == max)) return; + sd->date_min.tm_year = min > 2 ? min : 2; + if (max > sd->date_min.tm_year) + sd->date_max.tm_year = max; else - sd->year_max = sd->year_min; - if (sd->shown_time.tm_year > sd->year_max) - sd->shown_time.tm_year = sd->year_max; - if (sd->shown_time.tm_year < sd->year_min) - sd->shown_time.tm_year = sd->year_min; + sd->date_max.tm_year = sd->date_min.tm_year; + sd->date_min.tm_mon = 0; + sd->date_min.tm_mday = 1; + sd->date_max.tm_mon = 11; + sd->date_max.tm_mday = 31; + + if (sd->shown_time.tm_year > sd->date_max.tm_year) + sd->shown_time.tm_year = sd->date_max.tm_year; + if (sd->shown_time.tm_year < sd->date_min.tm_year) + sd->shown_time.tm_year = sd->date_min.tm_year; + evas_object_smart_changed(obj); } -EOLIAN static void +EAPI void _elm_calendar_min_max_year_get(Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd, int *min, int *max) { - if (min) *min = sd->year_min + 1900; - if (max) *max = sd->year_max + 1900; + if (min) *min = sd->date_min.tm_year + 1900; + if (max) *max = sd->date_max.tm_year + 1900; +} + +EOLIAN static void +_elm_calendar_date_min_set(Eo *obj, Elm_Calendar_Data *sd, const struct tm *min) +{ + Eina_Bool upper = EINA_FALSE; + + if ((sd->date_min.tm_year == min->tm_year) + && (sd->date_min.tm_mon == min->tm_mon) + && (sd->date_min.tm_mday == min->tm_mday)) + return; + + if (min->tm_year < 2) + { + sd->date_min.tm_year = 2; + sd->date_min.tm_mon = 0; + sd->date_min.tm_mday = 1; + } + else + { + if (sd->date_max.tm_year != -1) + { + if (min->tm_year > sd->date_max.tm_year) + { + upper = EINA_TRUE; + } + else if (min->tm_year == sd->date_max.tm_year) + { + if (min->tm_mon > sd->date_max.tm_mon) + upper = EINA_TRUE; + else if ((min->tm_mon == sd->date_max.tm_mon) && (min->tm_mday > sd->date_max.tm_mday)) + upper = EINA_TRUE; + } + } + + if (upper) + { + sd->date_min.tm_year = sd->date_max.tm_year; + sd->date_min.tm_mon = sd->date_max.tm_mon; + sd->date_min.tm_mday = sd->date_max.tm_mday; + } + else + { + sd->date_min.tm_year = min->tm_year; + sd->date_min.tm_mon = min->tm_mon; + sd->date_min.tm_mday = min->tm_mday; + } + } + + if (sd->shown_time.tm_year <= sd->date_min.tm_year) + { + sd->shown_time.tm_year = sd->date_min.tm_year; + if (sd->shown_time.tm_mon < sd->date_min.tm_mon) + sd->shown_time.tm_mon = sd->date_min.tm_mon; + } + + _fix_selected_time(sd); + + evas_object_smart_changed(obj); +} + +EOLIAN static const struct tm * +_elm_calendar_date_min_get(Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd) +{ + return &(sd->date_min); +} + +EOLIAN static void +_elm_calendar_date_max_set(Eo *obj, Elm_Calendar_Data *sd, const struct tm *max) +{ + Eina_Bool lower = EINA_FALSE; + + if ((sd->date_max.tm_year == max->tm_year) + && (sd->date_max.tm_mon == max->tm_mon) + && (sd->date_max.tm_mday == max->tm_mday)) + return; + + if (max->tm_year < sd->date_min.tm_year) + { + lower = EINA_TRUE; + } + else if (max->tm_year == sd->date_min.tm_year) + { + if (max->tm_mon < sd->date_min.tm_mon) + lower = EINA_TRUE; + else if ((max->tm_mon == sd->date_min.tm_mon) && (max->tm_mday < sd->date_min.tm_mday)) + lower = EINA_TRUE; + } + + if (lower) + { + sd->date_max.tm_year = sd->date_min.tm_year; + sd->date_max.tm_mon = sd->date_min.tm_mon; + sd->date_max.tm_mday = sd->date_min.tm_mday; + } + else + { + sd->date_max.tm_year = max->tm_year; + sd->date_max.tm_mon = max->tm_mon; + sd->date_max.tm_mday = max->tm_mday; + } + + if (sd->shown_time.tm_year >= sd->date_max.tm_year) + { + sd->shown_time.tm_year = sd->date_max.tm_year; + if (sd->shown_time.tm_mon > sd->date_max.tm_mon) + sd->shown_time.tm_mon = sd->date_max.tm_mon; + } + + _fix_selected_time(sd); + + evas_object_smart_changed(obj); +} + +EOLIAN static const struct tm * +_elm_calendar_date_max_get(Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd) +{ + return &(sd->date_max); } EINA_DEPRECATED EAPI void diff --git a/src/lib/elementary/elm_calendar.eo b/src/lib/elementary/elm_calendar.eo index 63fd34b57f..31169c99bd 100644 --- a/src/lib/elementary/elm_calendar.eo +++ b/src/lib/elementary/elm_calendar.eo @@ -187,30 +187,6 @@ class Elm.Calendar (Elm.Layout, Elm.Interface.Atspi_Widget_Action) mode: Elm.Calendar.Select.Mode; [[The select mode to use.]] } } - @property min_max_year { - [[The minimum and maximum values for the year - - Maximum must be greater than minimum, except if you don't want to set - maximum year. - Default values are 1902 and -1. - - If the maximum year is a negative value, it will be limited depending - on the platform architecture (year 2037 for 32 bits); - - See also @.min_max_year.get. - - \@ref calendar_example_03. - \@ref calendar_example_05. - ]] - set { - } - get { - } - values { - min: int; [[The minimum year, greater than 1901;]] - max: int; [[The maximum year;]] - } - } @property format_function { set { [[Set a function to format the string that will be used to display @@ -255,6 +231,58 @@ class Elm.Calendar (Elm.Layout, Elm.Interface.Atspi_Widget_Action) return: const(list); [[List with all calendar marks]] } } + @property date_min { + [[Minimum date on calendar. + + See also @.date_max.set, @.date_max.get + + @since 1.19 + ]] + set { + [[Set minimum date on calendar. + + Set the minimum date, changing the displayed month or year if needed. + Displayed day also to be disabled if it is smaller than minimum date. + ]] + } + get { + [[Get minimum date. + + Default value is 1 JAN,1902. + ]] + } + values { + min: const(Efl.Time)*; [[A tm struct to point to minimum date.]] + } + } + @property date_max { + [[Maximum date on calendar. + + See also @.date_min.set, @.date_min.get + + @since 1.19 + ]] + set { + [[Set maximum date on calendar. + + Set the maximum date, changing the displayed month or year if needed. + Displayed day also to be disabled if it is bigger than maximum date. + ]] + } + get { + [[Get maximum date. + + Default maximum year is -1. + Default maximum day and month are 31 and DEC. + + If the maximum year is a negative value, it will be limited depending + on the platform architecture (year 2037 for 32 bits); + ]] + } + values { + max: const(Efl.Time)*; [[A tm struct to point to maximum date.]] + } + } selected_time_set { [[Set selected date to be highlighted on calendar. diff --git a/src/lib/elementary/elm_calendar_legacy.h b/src/lib/elementary/elm_calendar_legacy.h index ddc8ac0d62..adb6a6b80e 100644 --- a/src/lib/elementary/elm_calendar_legacy.h +++ b/src/lib/elementary/elm_calendar_legacy.h @@ -28,3 +28,33 @@ EAPI Evas_Object *elm_calendar_add(Evas_Object *parent); * @ref calendar_example_06 */ EAPI void elm_calendar_mark_del(Elm_Calendar_Mark *mark); + +/** + * Set the minimum and maximum values for the year. + * + * @param min The minimum year, greater than 1901. + * @param max The maximum year. + * + * Maximum must be greater than minimum, except if you don't want to set maximum year. + * Default values are 1902 and -1. + * If the maximum year is a negative value, it will be limited depending on the platform architecture. (year 2037 for 32 bits) + * + * @see elm_calendar_min_max_year_get() + * + * @ref calendar_example_03 + */ +EAPI void elm_calendar_min_max_year_set(Elm_Calendar *obj, int min, int max); + +/** + * Get the minimum and maximum values for the year. + * + * @param[out] min The minimum year, greater than 1901. + * @param[out] max The maximum year. + * + * Default values are 1902 and -1. + * + * @see elm_calendar_min_max_year_set() + * + * @ref calendar_example_05 + */ +EAPI void elm_calendar_min_max_year_get(const Elm_Calendar *obj, int *min, int *max); diff --git a/src/lib/elementary/elm_widget_calendar.h b/src/lib/elementary/elm_widget_calendar.h index e7b92ab322..18d3cf7546 100644 --- a/src/lib/elementary/elm_widget_calendar.h +++ b/src/lib/elementary/elm_widget_calendar.h @@ -37,12 +37,12 @@ struct _Elm_Calendar_Data Evas_Object *obj; // the object itself Eina_List *marks; double interval, first_interval; - int year_min, year_max, spin_speed; + int spin_speed; int today_it, selected_it, first_day_it; Ecore_Timer *spin_month, *spin_year, *update_timer; Elm_Calendar_Format_Cb format_func; const char *weekdays[ELM_DAY_LAST]; - struct tm current_time, selected_time, shown_time; + struct tm current_time, selected_time, shown_time, date_min, date_max; Day_Color day_color[42]; // EINA_DEPRECATED Evas_Object *inc_btn_month; Evas_Object *dec_btn_month;