#ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #include #include "elm_priv.h" #include "efl_ui_datepicker_private.h" #define MY_CLASS EFL_UI_DATEPICKER_CLASS #define MY_CLASS_NAME "Efl.Ui.Datepicker" #define FMT_LEN_MAX 32 #define DATE_GET() \ do { \ Efl_Time t = efl_datetime_manager_value_get(pd->dt_manager); \ pd->cur_date[DATEPICKER_YEAR] = t.tm_year + 1900; \ pd->cur_date[DATEPICKER_MONTH] = t.tm_mon + 1; \ pd->cur_date[DATEPICKER_DAY] = t.tm_mday + 1; \ } while (0) #define DATE_SET() \ do { \ Efl_Time t = { 0 }; \ t.tm_year = pd->cur_date[DATEPICKER_YEAR] - 1900; \ t.tm_mon = pd->cur_date[DATEPICKER_MONTH] - 1; \ t.tm_mday = pd->cur_date[DATEPICKER_DAY] - 1; \ t.tm_sec = 0; \ efl_datetime_manager_value_set(pd->dt_manager, t); \ } while (0) static const char *fmt_char[] = {"Yy", "mbBh", "de"}; static Eina_Bool _validate_params(int year, int month, int day) { if (year < 1900 || year > 2037 || month < 1 || month > 12 || day < 0 || day > 31) return EINA_FALSE; else return EINA_TRUE; } static Eina_Bool _date_cmp(int time1[], int time2[]) { unsigned int idx; for (idx = 0; idx < EFL_UI_DATEPICKER_TYPE_COUNT; idx++) { if (time1[idx] != time2[idx]) return EINA_FALSE; } return EINA_TRUE; } static Eina_Bool _validate_date_limits(int time1[], int time2[], Eina_Bool swap) { unsigned int idx; int *t1, *t2; t1 = (swap) ? time2 : time1; t2 = (swap) ? time1 : time2; for (idx = 0; idx < EFL_UI_DATEPICKER_TYPE_COUNT; idx++) { if (time1[idx] < time2[idx]) { memcpy(t1, t2, (sizeof(int) * EFL_UI_DATEPICKER_TYPE_COUNT)); return EINA_TRUE; } else if (time1[idx] > time2[idx]) return EINA_FALSE; } return EINA_FALSE; } static int _max_days_get(int year, int month) { struct tm time1; time_t t; int day; t = time(NULL); localtime_r(&t, &time1); time1.tm_year = year; time1.tm_mon = month; for (day = 28; day <= 31; day++) { time1.tm_mday = day; mktime(&time1); /* To restrict month wrapping because of summer time in some locales, * ignore day light saving mode in mktime(). */ time1.tm_isdst = -1; if (time1.tm_mday == 1) break; } day--; return day; } static void _field_value_update(Eo *obj) { Efl_Ui_Datepicker_Data *pd = efl_data_scope_get(obj, MY_CLASS); efl_ui_range_value_set(pd->year, pd->cur_date[DATEPICKER_YEAR]); efl_ui_range_value_set(pd->month, pd->cur_date[DATEPICKER_MONTH]); efl_ui_range_value_set(pd->day, pd->cur_date[DATEPICKER_DAY]); DATE_SET(); } static void _field_changed_cb(void *data, const Efl_Event *ev) { int max_day; Efl_Ui_Datepicker_Data *pd = efl_data_scope_get(data, MY_CLASS); if (ev->object == pd->year) pd->cur_date[DATEPICKER_YEAR] = efl_ui_range_value_get(pd->year); else if (ev->object == pd->month) pd->cur_date[DATEPICKER_MONTH] = efl_ui_range_value_get(pd->month); else pd->cur_date[DATEPICKER_DAY] = efl_ui_range_value_get(pd->day); if (!(ev->object == pd->day)) { max_day = _max_days_get((pd->cur_date[DATEPICKER_YEAR] - 1900), (pd->cur_date[DATEPICKER_MONTH] - 1)); efl_ui_range_limits_set(pd->day, 1, max_day); } if (_validate_date_limits(pd->cur_date, pd->min_date, EINA_FALSE) || _validate_date_limits(pd->max_date, pd->cur_date, EINA_TRUE)) { _field_value_update(data); return; } DATE_SET(); efl_event_callback_call(data, EFL_UI_DATEPICKER_EVENT_DATE_CHANGED, NULL); } static void _fields_init(Eo *obj) { const char *fmt; char ch; int i; int field = 0; char buf[FMT_LEN_MAX]; Efl_Ui_Datepicker_Data *pd = efl_data_scope_get(obj, MY_CLASS); //Field create. pd->year = efl_add(EFL_UI_SPIN_BUTTON_CLASS, obj, efl_ui_range_limits_set(efl_added, 1900, 2037), efl_ui_spin_button_wraparound_set(efl_added, EINA_TRUE), efl_ui_spin_button_direct_text_input_set(efl_added, EINA_TRUE), efl_ui_layout_orientation_set(efl_added, EFL_UI_LAYOUT_ORIENTATION_VERTICAL), efl_event_callback_add(efl_added, EFL_UI_RANGE_EVENT_CHANGED,_field_changed_cb, obj)); pd->month = efl_add(EFL_UI_SPIN_BUTTON_CLASS, obj, efl_ui_range_limits_set(efl_added, 1, 12), efl_ui_spin_button_wraparound_set(efl_added, EINA_TRUE), efl_ui_spin_button_direct_text_input_set(efl_added, EINA_TRUE), efl_ui_layout_orientation_set(efl_added, EFL_UI_LAYOUT_ORIENTATION_VERTICAL), efl_event_callback_add(efl_added, EFL_UI_RANGE_EVENT_CHANGED,_field_changed_cb, obj)); pd->day = efl_add(EFL_UI_SPIN_BUTTON_CLASS, obj, efl_ui_range_limits_set(efl_added, 1, 31), efl_ui_spin_button_wraparound_set(efl_added, EINA_TRUE), efl_ui_spin_button_direct_text_input_set(efl_added, EINA_TRUE), efl_ui_layout_orientation_set(efl_added, EFL_UI_LAYOUT_ORIENTATION_VERTICAL), efl_event_callback_add(efl_added, EFL_UI_RANGE_EVENT_CHANGED,_field_changed_cb, obj)); DATE_GET(); //Using system config? pd->min_date[DATEPICKER_YEAR] = 1970; pd->min_date[DATEPICKER_MONTH] = 1; pd->min_date[DATEPICKER_DAY] = 1; pd->max_date[DATEPICKER_YEAR] = 2037; pd->max_date[DATEPICKER_MONTH] = 12; pd->max_date[DATEPICKER_DAY] = 31; _field_value_update(obj); fmt = efl_datetime_manager_format_get(pd->dt_manager); if (!fmt) { ERR("Failed to get current format."); //Gives default format when the gets format failed. fmt = "%Y %b %d"; } //Sort fields by format. while((ch = *fmt)) { //TODO: ignore extensions and separators. for (i = 0; i < EFL_UI_DATEPICKER_TYPE_COUNT; i++) { if (strchr(fmt_char[i], ch)) { snprintf(buf, sizeof(buf), "efl.field%d", field++); if (i == DATEPICKER_YEAR) efl_content_set(efl_part(obj, buf), pd->year); else if (i == DATEPICKER_MONTH) efl_content_set(efl_part(obj, buf), pd->month); else efl_content_set(efl_part(obj, buf), pd->day); break; } } fmt++; } } EOLIAN static Eo * _efl_ui_datepicker_efl_object_constructor(Eo *obj, Efl_Ui_Datepicker_Data *pd) { ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL); if (!elm_widget_theme_klass_get(obj)) elm_widget_theme_klass_set(obj, "datepicker"); obj = efl_constructor(efl_super(obj, MY_CLASS)); if (elm_widget_theme_object_set(obj, wd->resize_obj, elm_widget_theme_klass_get(obj), elm_widget_theme_element_get(obj), elm_widget_theme_style_get(obj)) == EFL_UI_THEME_APPLY_ERROR_GENERIC) CRI("Failed to set layout!"); pd->dt_manager = efl_add(EFL_DATETIME_MANAGER_CLASS, obj); _fields_init(obj); elm_widget_can_focus_set(obj, EINA_TRUE); return obj; } EOLIAN static void _efl_ui_datepicker_efl_object_destructor(Eo *obj, Efl_Ui_Datepicker_Data *pd) { efl_del(pd->dt_manager); efl_destructor(efl_super(obj, MY_CLASS)); } EOLIAN static void _efl_ui_datepicker_date_min_set(Eo *obj, Efl_Ui_Datepicker_Data *pd EINA_UNUSED, int year, int month, int day) { int new_time[EFL_UI_DATEPICKER_TYPE_COUNT] = {year, month, day}; if (!_validate_params(year, month, day)) return; if (_date_cmp(pd->min_date, new_time)) return; memcpy(pd->min_date, new_time, (sizeof(int) * EFL_UI_DATEPICKER_TYPE_COUNT)); _validate_date_limits(pd->max_date, pd->min_date, EINA_FALSE); _validate_date_limits(pd->cur_date, pd->min_date, EINA_FALSE); DATE_SET(); _field_value_update(obj); } EOLIAN static void _efl_ui_datepicker_date_min_get(const Eo *obj EINA_UNUSED, Efl_Ui_Datepicker_Data *pd, int *year, int *month, int *day) { *year = pd->min_date[DATEPICKER_YEAR]; *month = pd->min_date[DATEPICKER_MONTH]; *day = pd->min_date[DATEPICKER_DAY]; } EOLIAN static void _efl_ui_datepicker_date_max_set(Eo *obj, Efl_Ui_Datepicker_Data *pd EINA_UNUSED, int year, int month, int day) { int new_time[EFL_UI_DATEPICKER_TYPE_COUNT] = {year, month, day}; if (!_validate_params(year, month, day)) return; if (_date_cmp(pd->max_date, new_time)) return; memcpy(pd->max_date, new_time, (sizeof(int) * EFL_UI_DATEPICKER_TYPE_COUNT)); _validate_date_limits(pd->max_date, pd->min_date, EINA_TRUE); _validate_date_limits(pd->max_date, pd->cur_date, EINA_TRUE); DATE_SET(); _field_value_update(obj); } EOLIAN static void _efl_ui_datepicker_date_max_get(const Eo *obj EINA_UNUSED, Efl_Ui_Datepicker_Data *pd, int *year, int *month, int *day) { *year = pd->max_date[DATEPICKER_YEAR]; *month = pd->max_date[DATEPICKER_MONTH]; *day = pd->max_date[DATEPICKER_DAY]; } EOLIAN static void _efl_ui_datepicker_date_set(Eo *obj, Efl_Ui_Datepicker_Data *pd, int year, int month, int day) { int new_time[EFL_UI_DATEPICKER_TYPE_COUNT] = {year, month, day}; if (!_validate_params(year, month, day)) return; if (_date_cmp(pd->cur_date, new_time)) return; memcpy(pd->cur_date, new_time, (sizeof(int) * EFL_UI_DATEPICKER_TYPE_COUNT)); _validate_date_limits(pd->cur_date, pd->min_date, EINA_FALSE); _validate_date_limits(pd->max_date, pd->cur_date, EINA_TRUE); DATE_SET(); _field_value_update(obj); } EOLIAN static void _efl_ui_datepicker_date_get(const Eo *obj EINA_UNUSED, Efl_Ui_Datepicker_Data *pd, int *year, int *month, int *day) { *year = pd->cur_date[DATEPICKER_YEAR]; *month = pd->cur_date[DATEPICKER_MONTH]; *day = pd->cur_date[DATEPICKER_DAY]; } #include "efl_ui_datepicker.eo.c"