2 # include "elementary_config.h"
5 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
7 #include <Elementary.h>
9 #include "elm_widget_datetime.h"
11 #define MY_CLASS ELM_DATETIME_CLASS
13 #define MY_CLASS_NAME "Elm_Datetime"
14 #define MY_CLASS_NAME_LEGACY "elm_datetime"
20 #ifdef HAVE_LANGINFO_H
21 # include <langinfo.h>
24 #define MAX_SEPARATOR_LEN 6
25 #define MIN_DAYS_IN_MONTH 28
26 #define BUFFER_SIZE 1024
28 /* interface between EDC & C code (field & signal names). values 0 to
29 * ELM_DATETIME_TYPE_COUNT are in the valid range, and must get in the
32 #define EDC_DATETIME_FOCUSIN_SIG_STR "elm,action,focus"
33 #define EDC_DATETIME_FOCUSOUT_SIG_STR "elm,action,unfocus"
34 #define EDC_PART_FIELD_STR "field%d"
35 #define EDC_PART_SEPARATOR_STR "separator%d"
36 #define EDC_PART_FIELD_ENABLE_SIG_STR "field%d,enable"
37 #define EDC_PART_FIELD_DISABLE_SIG_STR "field%d,disable"
39 /* struct tm does not define the fields in the order year, month,
40 * date, hour, minute. values are reassigned to an array for easy
43 #define DATETIME_TM_ARRAY(intptr, tmptr) \
52 // default limits for individual fields
53 static Format_Map mapping[ELM_DATETIME_TYPE_COUNT] = {
54 [ELM_DATETIME_YEAR] = { "Yy", -1, -1, "" },
55 [ELM_DATETIME_MONTH] = { "mbBh", 0, 11, "" },
56 [ELM_DATETIME_DATE] = { "de", 1, 31, "" },
57 [ELM_DATETIME_HOUR] = { "IHkl", 0, 23, "" },
58 [ELM_DATETIME_MINUTE] = { "M", 0, 59, ":" },
59 [ELM_DATETIME_AMPM] = { "pP", 0, 1, "" }
62 static const char *multifield_formats = "cxXrRTDF";
63 static const char *ignore_separators = "()";
64 static const char *ignore_extensions = "E0_-O^#";
65 static Datetime_Mod_Api *dt_mod = NULL;
67 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
68 {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
69 {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
70 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
71 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
75 static Datetime_Mod_Api *
78 Elm_Module *mod = NULL;
80 if (!(mod = _elm_module_find_as("datetime/api"))) return NULL;
82 mod->api = malloc(sizeof(Datetime_Mod_Api));
83 if (!mod->api) return NULL;
85 ((Datetime_Mod_Api *)(mod->api))->obj_hook =
86 _elm_module_symbol_get(mod, "obj_hook");
87 ((Datetime_Mod_Api *)(mod->api))->obj_unhook =
88 _elm_module_symbol_get(mod, "obj_unhook");
89 ((Datetime_Mod_Api *)(mod->api))->obj_hide =
90 _elm_module_symbol_get(mod, "obj_hide");
91 ((Datetime_Mod_Api *)(mod->api))->field_create =
92 _elm_module_symbol_get(mod, "field_create");
93 ((Datetime_Mod_Api *)(mod->api))->field_value_display =
94 _elm_module_symbol_get(mod, "field_value_display");
95 //TIZEN_ONLY(20151218): Support Mobile UX
96 ((Datetime_Mod_Api *)(mod->api))->field_format_changed =
97 _elm_module_symbol_get(mod, "field_format_changed");
104 _field_list_display(Evas_Object *obj)
106 Datetime_Field *field;
107 unsigned int idx = 0;
109 ELM_DATETIME_DATA_GET(obj, sd);
111 if (!dt_mod || !dt_mod->field_value_display) return;
113 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
115 field = sd->field_list + idx;
116 if (field->fmt_exist && field->visible)
117 dt_mod->field_value_display(sd->mod_data, field->item_obj);
121 // FIXME: provide nl_langinfo on Windows if possible
122 // returns expanded format string for corresponding multi-field format character
124 _expanded_fmt_str_get(char ch)
130 #if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
131 exp_fmt = nl_langinfo(D_T_FMT);
138 #if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
139 exp_fmt = nl_langinfo(D_FMT);
146 #if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
147 exp_fmt = nl_langinfo(T_FMT);
154 #if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
155 exp_fmt = nl_langinfo(T_FMT_AMPM);
166 exp_fmt = "%H:%M:%S";
170 exp_fmt = "%m/%d/%y";
174 exp_fmt = "%Y-%m-%d";
186 _expand_format(char *dt_fmt)
188 char *ptr, *expanded_fmt, ch;
189 unsigned int idx, len = 0;
190 char buf[ELM_DATETIME_MAX_FORMAT_LEN] = {0, };
191 Eina_Bool fmt_char, fmt_expanded;
195 fmt_char = EINA_FALSE;
196 fmt_expanded = EINA_FALSE;
200 if ((fmt_char) && (strchr(multifield_formats, ch)))
202 /* replace the multi-field format characters with
203 * corresponding expanded format */
204 expanded_fmt = _expanded_fmt_str_get(ch);
205 len = strlen(expanded_fmt);
206 if (len > 0) fmt_expanded = EINA_TRUE;
208 strncat(buf, expanded_fmt, len);
211 else buf[idx++] = ch;
213 if (ch == '%') fmt_char = EINA_TRUE;
214 else fmt_char = EINA_FALSE;
220 strncpy(dt_fmt, buf, ELM_DATETIME_MAX_FORMAT_LEN);
221 } while (fmt_expanded);
225 _field_list_arrange(Evas_Object *obj)
227 Datetime_Field *field;
228 char buf[BUFFER_SIZE];
232 ELM_DATETIME_DATA_GET(obj, sd);
234 freeze = sd->freeze_sizing;
235 sd->freeze_sizing = EINA_TRUE;
237 //////////////////////////////////////////////////////////////////////////////
238 //TIZEN_ONLY(20150225): Open source datetime code doesn't consider dynamically
239 // field sequence changing case.
241 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
243 field = sd->field_list + idx;
244 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location);
246 if (field->visible && field->fmt_exist)
248 elm_layout_content_unset(obj, buf);
249 elm_layout_content_set(obj, buf, field->item_obj);
252 evas_object_hide(elm_layout_content_unset(obj, buf));
255 // remove all the content widget from the layout
256 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
258 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, idx);
259 elm_layout_content_unset(obj, buf);
261 // set as content widget or hide it depending on location
262 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
264 field = sd->field_list + idx;
265 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location);
267 if (field->visible && field->fmt_exist)
268 elm_layout_content_set(obj, buf, field->item_obj);
270 evas_object_hide(field->item_obj);
272 //////////////////////////////////////////////////////////////////////////////
274 sd->freeze_sizing = freeze;
276 elm_layout_sizing_eval(obj);
277 _field_list_display(obj);
281 _parse_format(Evas_Object *obj,
284 Eina_Bool fmt_parsing = EINA_FALSE, sep_parsing = EINA_FALSE,
285 sep_lookup = EINA_FALSE;
286 //TIZEN_ONLY(20151216) - swap format locations to support some locale.
287 Eina_Bool location_swap = EINA_FALSE;
289 unsigned int len = 0, idx = 0, location = 0;
290 char separator[MAX_SEPARATOR_LEN];
291 Datetime_Field *field = NULL;
294 ELM_DATETIME_DATA_GET(obj, sd);
296 while ((cur = *fmt_ptr))
300 if (strchr(ignore_extensions, cur))
305 fmt_parsing = EINA_FALSE;
307 //TIZEN_ONLY(20151216) - swap format locations to support some locale.
309 (strchr(mapping[ELM_DATETIME_HOUR].fmt_char, cur) ||
310 strchr(mapping[ELM_DATETIME_MINUTE].fmt_char, cur) ||
311 strchr(mapping[ELM_DATETIME_AMPM].fmt_char, cur)))
312 location_swap = EINA_TRUE;
314 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
316 if (strchr(mapping[idx].fmt_char, cur))
318 field = sd->field_list + idx;
319 /* ignore the fields already have or disabled
320 * valid formats, means already parsed &
321 * repeated, ignore. */
322 if (field->location != -1) break;
324 field->fmt_exist = EINA_TRUE;
325 field->location = location++;
326 sep_lookup = EINA_TRUE;
334 fmt_parsing = EINA_TRUE;
335 sep_parsing = EINA_FALSE;
336 // set the separator to previous field
338 if (field) eina_stringshare_replace(&field->separator, separator);
340 // ignore the set of chars (global, field specific) as field separators
342 (len < MAX_SEPARATOR_LEN - 1) &&
343 (field->type != ELM_DATETIME_AMPM) &&
344 (!strchr(ignore_separators, cur)) &&
345 (!strchr(mapping[idx].ignore_sep, cur)))
346 separator[len++] = cur;
347 if (sep_lookup) sep_parsing = EINA_TRUE;
348 sep_lookup = EINA_FALSE;
352 //TIZEN_ONLY(20151216) - swap format locations to support some locale.
357 time_fmt_count = location - ELM_DATETIME_HOUR;
358 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
360 field = sd->field_list + idx;
361 /* ignore the fields already disabled
362 * valid formats, means already ignore. */
363 if (field->location == -1) continue;
364 if (idx < ELM_DATETIME_HOUR)
365 field->location -= time_fmt_count;
367 field->location += ELM_DATETIME_HOUR;
372 // return the number of valid fields parsed.
376 // TIZEN_ONLY(20151218): Support Mobile UX
378 _notify_format_change(Evas_Object *obj)
380 Datetime_Field *field;
381 unsigned int idx = 0;
383 ELM_DATETIME_DATA_GET(obj, sd);
385 if (!dt_mod || !dt_mod->field_format_changed) return;
387 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
389 field = sd->field_list + idx;
391 dt_mod->field_format_changed(sd->mod_data, field->item_obj);
397 _reload_format(Evas_Object *obj)
399 unsigned int idx, field_count;
400 Datetime_Field *field;
401 char buf[BUFFER_SIZE];
404 ELM_DATETIME_DATA_GET(obj, sd);
405 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
407 // FIXME: provide nl_langinfo on Windows if possible
408 // fetch the default format from Libc.
409 if (!sd->user_format)
410 #if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
411 strncpy(sd->format, nl_langinfo(D_T_FMT), ELM_DATETIME_MAX_FORMAT_LEN);
413 strncpy(sd->format, "", ELM_DATETIME_MAX_FORMAT_LEN);
415 sd->format[ELM_DATETIME_MAX_FORMAT_LEN - 1] = '\0';
417 dt_fmt = (char *)malloc(ELM_DATETIME_MAX_FORMAT_LEN);
420 strncpy(dt_fmt, sd->format, ELM_DATETIME_MAX_FORMAT_LEN);
422 _expand_format(dt_fmt);
424 // reset all the fields to disable state
425 sd->enabled_field_count = 0;
426 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
428 field = sd->field_list + idx;
429 field->fmt_exist = EINA_FALSE;
430 field->location = -1;
433 field_count = _parse_format(obj, dt_fmt);
436 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
438 field = sd->field_list + idx;
439 if (field->fmt_exist && field->visible)
440 sd->enabled_field_count++;
443 // assign locations to disabled fields for uniform usage
444 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
446 field = sd->field_list + idx;
447 if (field->location == -1) field->location = field_count++;
449 if (field->fmt_exist && field->visible)
451 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR,
453 elm_layout_signal_emit(obj, buf, "elm");
457 snprintf(buf, sizeof(buf), EDC_PART_FIELD_DISABLE_SIG_STR,
459 elm_layout_signal_emit(obj, buf, "elm");
462 (buf, sizeof(buf), EDC_PART_SEPARATOR_STR, (field->location + 1));
463 elm_layout_text_set(obj, buf, field->separator);
466 edje_object_message_signal_process(wd->resize_obj);
467 _field_list_arrange(obj);
469 //TIZEN_ONLY(20151218): Support Mobile UX
470 _notify_format_change(obj);
474 EOLIAN static Eina_Bool
475 _elm_datetime_elm_widget_translate(Eo *obj, Elm_Datetime_Data *sd)
477 if (!sd->user_format) _reload_format(obj);
478 else _field_list_display(obj);
480 eo_do_super(obj, MY_CLASS, elm_obj_widget_translate());
486 _datetime_items_get(const Evas_Object *obj)
488 Eina_List *items = NULL;
489 Datetime_Field *field;
491 //TIZEN_ONLY(20170818): Prevent Null pointer ref.
492 Datetime_Field *sorted_fields[ELM_DATETIME_TYPE_COUNT] = {0};
493 //Datetime_Field *sorted_fields[ELM_DATETIME_TYPE_COUNT];
496 ELM_DATETIME_DATA_GET(obj, sd);
498 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
500 field = sd->field_list + idx;
501 sorted_fields[field->location] = field;
504 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
506 field = sorted_fields[idx];
507 //TIZEN_ONLY(20170818): Prevent Null pointer ref.
508 if (!field) continue;
510 if (field->fmt_exist && field->visible)
511 items = eina_list_append(items, field->item_obj);
515 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
516 items = eina_list_append(items, sd->access_obj);
521 EOLIAN static Eina_Bool
522 _elm_datetime_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Datetime_Data *_pd EINA_UNUSED)
527 EOLIAN static Eina_Bool
528 _elm_datetime_elm_widget_focus_next(Eo *obj, Elm_Datetime_Data *_pd EINA_UNUSED, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
530 const Eina_List *items;
531 Eina_List *(*list_free)(Eina_List *list);
532 void *(*list_data_get)(const Eina_List *list);
536 if ((items = elm_widget_focus_custom_chain_get(obj)))
538 list_data_get = eina_list_data_get;
543 items = _datetime_items_get(obj);
544 list_data_get = eina_list_data_get;
545 list_free = eina_list_free;
546 if (!items) return EINA_FALSE;
549 int_ret = elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next, next_item);
550 if (list_free) list_free((Eina_List *)items);
555 EOLIAN static Eina_Bool
556 _elm_datetime_elm_widget_on_focus(Eo *obj, Elm_Datetime_Data *sd, Elm_Object_Item *item EINA_UNUSED)
558 Eina_Bool int_ret = EINA_FALSE;
560 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_on_focus(NULL));
561 if (!int_ret) return EINA_FALSE;
563 if (!elm_widget_focus_get(obj))
565 if ((dt_mod) && (dt_mod->obj_hide))
566 dt_mod->obj_hide(sd->mod_data);
572 EOLIAN static Eina_Bool
573 _elm_datetime_elm_widget_disable(Eo *obj, Elm_Datetime_Data *sd)
575 Datetime_Field *field;
576 unsigned int idx = 0;
577 Eina_Bool int_ret = EINA_FALSE;
579 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_disable());
580 if (!int_ret) return EINA_FALSE;
582 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
584 field = sd->field_list + idx;
585 elm_object_disabled_set(field->item_obj, elm_object_disabled_get(obj));
591 _elm_datetime_elm_layout_sizing_eval(Eo *obj, Elm_Datetime_Data *sd)
593 Evas_Coord minw = -1, minh = -1;
595 if (sd->freeze_sizing) return;
597 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
599 if (sd->enabled_field_count)
600 elm_coords_finger_size_adjust(sd->enabled_field_count, &minw, 1, &minh);
602 edje_object_size_min_restricted_calc
603 (wd->resize_obj, &minw, &minh, minw, minh);
604 evas_object_size_hint_min_set(obj, minw, minh);
605 evas_object_size_hint_max_set(obj, -1, -1);
608 EOLIAN static Elm_Theme_Apply
609 _elm_datetime_elm_widget_theme_apply(Eo *obj, Elm_Datetime_Data *sd)
611 Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED;
613 Datetime_Field *field;
614 char buf[BUFFER_SIZE];
617 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_THEME_APPLY_FAILED);
619 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
620 if (!int_ret) return ELM_THEME_APPLY_FAILED;
622 if ((!dt_mod) || (!dt_mod->field_value_display)) return int_ret;
624 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
626 field = sd->field_list + idx;
627 if (field->fmt_exist && field->visible)
629 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR,
631 elm_layout_signal_emit(obj, buf, "elm");
634 (buf, sizeof(buf), EDC_PART_SEPARATOR_STR, field->location);
635 elm_layout_text_set(obj, buf, field->separator);
637 dt_mod->field_value_display(sd->mod_data, field->item_obj);
641 snprintf(buf, sizeof(buf), EDC_PART_FIELD_DISABLE_SIG_STR,
643 elm_layout_signal_emit(obj, buf, "elm");
647 edje_object_message_signal_process(wd->resize_obj);
648 elm_layout_sizing_eval(obj);
653 //TIZEN_ONLY(20170807): Apply UI Mirroring for Tizen 4.0 UX
654 EOLIAN static Eina_Bool
655 _elm_datetime_elm_widget_mirrored_get(Eo *obj EINA_UNUSED, Elm_Datetime_Data *sd EINA_UNUSED)
661 _elm_datetime_elm_widget_mirrored_set(Eo *obj EINA_UNUSED, Elm_Datetime_Data *sd EINA_UNUSED, Eina_Bool mirrored EINA_UNUSED)
668 _max_days_get(int year,
676 localtime_r(&t, &time1);
677 time1.tm_year = year;
678 time1.tm_mon = month;
679 for (day = MIN_DAYS_IN_MONTH; day <= mapping[ELM_DATETIME_DATE].def_max;
684 /* To restrict month wrapping because of summer time in some locales,
685 * ignore day light saving mode in mktime(). */
687 if (time1.tm_mday == 1) break;
695 _date_cmp(const struct tm *time1,
696 const struct tm *time2)
700 const DATETIME_TM_ARRAY(timearr1, time1);
701 const DATETIME_TM_ARRAY(timearr2, time2);
703 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
705 if (*timearr1[idx] != *timearr2[idx])
713 _field_cmp(Elm_Datetime_Field_Type field_type,
717 DATETIME_TM_ARRAY(timearr1, time1);
718 DATETIME_TM_ARRAY(timearr2, time2);
720 if (*timearr1[field_type] != *timearr2[field_type])
726 // validates curr_time/min_limt/max_limit according to the newly set value
728 _validate_datetime_limits(struct tm *time1,
735 if (!time1 || !time2) return;
737 t1 = (swap) ? time2 : time1;
738 t2 = (swap) ? time1 : time2;
740 DATETIME_TM_ARRAY(timearr1, time1);
741 DATETIME_TM_ARRAY(timearr2, time2);
742 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT - 1; idx++)
744 if (*timearr1[idx] < *timearr2[idx])
746 memcpy(t1, t2, sizeof(struct tm));
749 else if (*timearr1[idx] > *timearr2[idx])
755 _apply_field_limits(Evas_Object *obj)
757 Datetime_Field *field;
758 unsigned int idx = 0;
761 ELM_DATETIME_DATA_GET(obj, sd);
763 DATETIME_TM_ARRAY(timearr, &sd->curr_time);
764 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT - 1; idx++)
766 field = sd->field_list + idx;
768 if (val < field->min)
769 *timearr[idx] = field->min;
770 else if (val > field->max)
771 *timearr[idx] = field->max;
774 _field_list_display(obj);
778 _apply_range_restrictions(struct tm *tim)
785 DATETIME_TM_ARRAY(timearr, tim);
786 for (idx = ELM_DATETIME_MONTH; idx < ELM_DATETIME_TYPE_COUNT - 1; idx++)
789 min = mapping[idx].def_min;
790 max = mapping[idx].def_max;
791 if (idx == ELM_DATETIME_DATE)
792 max = _max_days_get(tim->tm_year, tim->tm_mon);
801 _field_format_get(Evas_Object *obj,
802 Elm_Datetime_Field_Type field_type)
804 Datetime_Field *field;
806 if (field_type > ELM_DATETIME_AMPM) return NULL;
808 ELM_DATETIME_DATA_GET(obj, sd);
810 field = sd->field_list + field_type;
816 _field_limit_get(Evas_Object *obj,
817 Elm_Datetime_Field_Type field_type,
821 int min, max, max_days;
822 Datetime_Field *field;
825 if (field_type > ELM_DATETIME_MINUTE) return;
827 ELM_DATETIME_DATA_GET(obj, sd);
829 field = sd->field_list + field_type;
834 DATETIME_TM_ARRAY(curr_timearr, &sd->curr_time);
835 DATETIME_TM_ARRAY(min_timearr, &sd->min_limit);
836 DATETIME_TM_ARRAY(max_timearr, &sd->max_limit);
838 for (idx = 0; idx < field->type; idx++)
839 if (*curr_timearr[idx] > *min_timearr[idx]) break;
840 if ((idx == field_type) && (min < *min_timearr[field_type]))
841 min = *min_timearr[field_type];
842 if (field_type == ELM_DATETIME_DATE)
844 max_days = _max_days_get(sd->curr_time.tm_year, sd->curr_time.tm_mon);
845 if (max > max_days) max = max_days;
847 for (idx = 0; idx < field->type; idx++)
848 if (*curr_timearr[idx] < *max_timearr[idx]) break;
849 if ((idx == field_type) && (max > *max_timearr[field_type]))
850 max = *max_timearr[field_type];
856 //TIZEN_ONLY(20151218): Support Mobile UX
858 _field_location_get(Evas_Object *obj, Elm_Datetime_Field_Type field_type,
861 Datetime_Field *field;
863 ELM_DATETIME_DATA_GET(obj, sd);
865 field = sd->field_list + field_type;
866 if (!field) return EINA_FALSE;
868 if (loc) *loc = field->location;
870 return (field->fmt_exist && field->visible);
874 _fields_sorted_get(Evas_Object *obj)
876 Eina_List *items = NULL;
877 Datetime_Field *field;
879 Datetime_Field *sorted_fields[ELM_DATETIME_TYPE_COUNT];
881 ELM_DATETIME_DATA_GET(obj, sd);
883 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
885 field = sd->field_list + idx;
886 sorted_fields[field->location] = field;
889 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
891 field = sorted_fields[idx];
892 if (field->fmt_exist && field->visible)
893 items = eina_list_append(items, field->item_obj);
901 _field_list_init(Evas_Object *obj)
903 Datetime_Field *field;
907 ELM_DATETIME_DATA_GET(obj, sd);
910 localtime_r(&t, &sd->curr_time);
912 mapping[ELM_DATETIME_YEAR].def_min = _elm_config->year_min;
913 mapping[ELM_DATETIME_YEAR].def_max = _elm_config->year_max;
914 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
916 field = sd->field_list + idx;
917 field->type = ELM_DATETIME_YEAR + idx;
919 field->fmt_exist = EINA_FALSE;
920 field->visible = EINA_TRUE;
921 field->min = mapping[idx].def_min;
922 field->max = mapping[idx].def_max;
924 DATETIME_TM_ARRAY(min_timearr, &sd->min_limit);
925 DATETIME_TM_ARRAY(max_timearr, &sd->max_limit);
926 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT - 1; idx++)
928 *min_timearr[idx] = mapping[idx].def_min;
929 *max_timearr[idx] = mapping[idx].def_max;
934 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
938 buf = eina_strbuf_new();
940 ELM_DATETIME_DATA_GET(data, sd);
941 eina_strbuf_append_printf(buf,
942 "%d year, %d month, %d date, %d hour, %d minute",
943 sd->curr_time.tm_year, sd->curr_time.tm_mon + 1,
944 sd->curr_time.tm_mday, sd->curr_time.tm_hour,
945 sd->curr_time.tm_min);
947 ret = eina_strbuf_string_steal(buf);
948 eina_strbuf_free(buf);
953 _elm_datetime_evas_object_smart_add(Eo *obj, Elm_Datetime_Data *priv)
955 Datetime_Field *field;
958 eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
959 elm_widget_sub_object_parent_add(obj);
961 /* TIZEN_ONLY(20180111): elm_widget_can_focus_set before module init for support TV UX */
962 elm_widget_can_focus_set(obj, EINA_TRUE);
965 // module - initialise module for datetime
966 if (!dt_mod) dt_mod = _dt_mod_init();
969 if (dt_mod->obj_hook)
971 priv->mod_data = dt_mod->obj_hook(obj);
973 // update module data
976 priv->mod_data->base = obj;
977 priv->mod_data->field_limit_get = _field_limit_get;
978 priv->mod_data->field_format_get = _field_format_get;
979 //TIZEN_ONLY(20151218): Support Mobile UX
980 priv->mod_data->field_location_get = _field_location_get;
981 priv->mod_data->fields_sorted_get = _fields_sorted_get;
986 if (dt_mod->field_create)
988 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
990 field = priv->field_list + idx;
991 field->item_obj = dt_mod->field_create(priv->mod_data, idx);
992 /* TIZEN_ONLY(20161031): apply color_class parent-child relationship to all widgets */
993 _elm_widget_color_class_parent_set(field->item_obj, obj);
999 priv->freeze_sizing = EINA_TRUE;
1000 if (!elm_layout_theme_set(obj, "datetime", "base",
1001 elm_widget_style_get(obj)))
1002 CRI("Failed to set layout!");
1004 _field_list_init(obj);
1005 _reload_format(obj);
1007 /* TIZEN_ONLY(20180111): elm_widget_can_focus_set before module init for support TV UX */
1008 //elm_widget_can_focus_set(obj, EINA_TRUE);
1011 priv->freeze_sizing = EINA_FALSE;
1012 elm_layout_sizing_eval(obj);
1015 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
1017 Elm_Access_Info *ai;
1019 priv->access_obj = _elm_access_edje_object_part_object_register
1020 (obj, elm_layout_edje_get(obj), "elm.access");
1021 if (!priv->access_obj)
1022 priv->access_obj = _elm_access_edje_object_part_object_register
1023 (obj, elm_layout_edje_get(obj), "access");
1025 ai = _elm_access_info_get(priv->access_obj);
1026 _elm_access_text_set(ai, ELM_ACCESS_TYPE, "date time");
1027 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, obj);
1032 _elm_datetime_evas_object_smart_del(Eo *obj, Elm_Datetime_Data *sd)
1034 Datetime_Field *tmp;
1037 for (idx = 0; idx < ELM_DATETIME_TYPE_COUNT; idx++)
1039 tmp = sd->field_list + idx;
1040 evas_object_del(tmp->item_obj);
1041 eina_stringshare_del(tmp->separator);
1044 if ((dt_mod) && (dt_mod->obj_unhook))
1045 dt_mod->obj_unhook(sd->mod_data); // module - unhook
1047 eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
1051 elm_datetime_add(Evas_Object *parent)
1053 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1054 Evas_Object *obj = eo_add(MY_CLASS, parent);
1059 _elm_datetime_eo_base_constructor(Eo *obj, Elm_Datetime_Data *_pd EINA_UNUSED)
1061 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
1063 evas_obj_type_set(MY_CLASS_NAME_LEGACY),
1064 evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
1065 elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_DATE_EDITOR));
1070 EOLIAN static const char*
1071 _elm_datetime_format_get(Eo *obj EINA_UNUSED, Elm_Datetime_Data *sd)
1077 _elm_datetime_format_set(Eo *obj, Elm_Datetime_Data *sd, const char *fmt)
1081 strncpy(sd->format, fmt, ELM_DATETIME_MAX_FORMAT_LEN);
1082 sd->format[ELM_DATETIME_MAX_FORMAT_LEN - 1] = '\0';
1083 sd->user_format = EINA_TRUE;
1085 else sd->user_format = EINA_FALSE;
1087 _reload_format(obj);
1090 EOLIAN static Eina_Bool
1091 _elm_datetime_field_visible_get(const Eo *obj EINA_UNUSED, Elm_Datetime_Data *sd, Elm_Datetime_Field_Type fieldtype)
1093 Datetime_Field *field;
1095 if (fieldtype > ELM_DATETIME_AMPM) return EINA_FALSE;
1097 field = sd->field_list + fieldtype;
1099 return field->visible;
1103 _elm_datetime_field_visible_set(Eo *obj, Elm_Datetime_Data *sd, Elm_Datetime_Field_Type fieldtype, Eina_Bool visible)
1105 char buf[BUFFER_SIZE];
1106 Datetime_Field *field;
1108 if (fieldtype > ELM_DATETIME_AMPM) return;
1110 field = sd->field_list + fieldtype;
1111 visible = !!visible;
1112 if (field->visible == visible) return;
1114 field->visible = visible;
1116 sd->freeze_sizing = EINA_TRUE;
1119 sd->enabled_field_count++;
1121 if (!field->fmt_exist) return;
1123 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR,
1125 elm_layout_signal_emit(obj, buf, "elm");
1127 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1128 edje_object_message_signal_process(wd->resize_obj);
1130 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location);
1131 elm_layout_content_unset(obj, buf);
1132 elm_layout_content_set(obj, buf, field->item_obj);
1136 sd->enabled_field_count--;
1138 if (!field->fmt_exist) return;
1140 snprintf(buf, sizeof(buf), EDC_PART_FIELD_DISABLE_SIG_STR,
1142 elm_layout_signal_emit(obj, buf, "elm");
1144 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1145 edje_object_message_signal_process(wd->resize_obj);
1147 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location);
1148 evas_object_hide(elm_layout_content_unset(obj, buf));
1150 sd->freeze_sizing = EINA_FALSE;
1152 elm_layout_sizing_eval(obj);
1154 if (!visible) return;
1155 if (!dt_mod || !dt_mod->field_value_display) return;
1157 dt_mod->field_value_display(sd->mod_data, field->item_obj);
1161 _elm_datetime_field_limit_get(const Eo *obj EINA_UNUSED, Elm_Datetime_Data *sd, Elm_Datetime_Field_Type fieldtype, int *min, int *max)
1163 Datetime_Field *field;
1165 if (fieldtype >= ELM_DATETIME_AMPM) return;
1167 field = sd->field_list + fieldtype;
1168 if (min) *min = field->min;
1169 if (max) *max = field->max;
1173 _elm_datetime_field_limit_set(Eo *obj, Elm_Datetime_Data *sd, Elm_Datetime_Field_Type fieldtype, int min, int max)
1175 Datetime_Field *field;
1178 if (fieldtype >= ELM_DATETIME_AMPM) return;
1180 if (min > max) return;
1182 old_time = sd->curr_time;
1183 field = sd->field_list + fieldtype;
1184 if (((min >= mapping[fieldtype].def_min) &&
1185 (min <= mapping[fieldtype].def_max)) ||
1186 (field->type == ELM_DATETIME_YEAR))
1188 if (((max >= mapping[fieldtype].def_min) &&
1189 (max <= mapping[fieldtype].def_max)) ||
1190 (field->type == ELM_DATETIME_YEAR))
1193 _apply_field_limits(obj);
1195 if (!_field_cmp(fieldtype, &old_time, &sd->curr_time))
1196 eo_do(obj, eo_event_callback_call(ELM_DATETIME_EVENT_CHANGED, NULL));
1200 EOLIAN static Eina_Bool
1201 _elm_datetime_value_get(const Eo *obj EINA_UNUSED, Elm_Datetime_Data *sd, struct tm *currtime)
1203 EINA_SAFETY_ON_NULL_RETURN_VAL(currtime, EINA_FALSE);
1205 *currtime = sd->curr_time;
1209 EOLIAN static Eina_Bool
1210 _elm_datetime_value_set(Eo *obj, Elm_Datetime_Data *sd, const struct tm *newtime)
1212 EINA_SAFETY_ON_NULL_RETURN_VAL(newtime, EINA_FALSE);
1214 if (_date_cmp(&sd->curr_time, newtime)) return EINA_TRUE;
1215 sd->curr_time = *newtime;
1216 // apply default field restrictions for curr_time
1217 _apply_range_restrictions(&sd->curr_time);
1218 // validate the curr_time according to the min_limt and max_limt
1219 _validate_datetime_limits(&sd->curr_time, &sd->min_limit, EINA_FALSE);
1220 _validate_datetime_limits(&sd->max_limit, &sd->curr_time, EINA_TRUE);
1221 _apply_field_limits(obj);
1223 eo_do(obj, eo_event_callback_call(ELM_DATETIME_EVENT_CHANGED, NULL));
1228 EOLIAN static Eina_Bool
1229 _elm_datetime_value_min_get(const Eo *obj EINA_UNUSED, Elm_Datetime_Data *sd, struct tm *mintime)
1231 EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE);
1233 *mintime = sd->min_limit;
1237 EOLIAN static Eina_Bool
1238 _elm_datetime_value_min_set(Eo *obj, Elm_Datetime_Data *sd, const struct tm *mintime)
1242 EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE);
1244 if (_date_cmp(&sd->min_limit, mintime)) return EINA_TRUE;
1245 sd->min_limit = *mintime;
1246 old_time = sd->curr_time;
1247 // apply default field restrictions for min_limit
1248 _apply_range_restrictions(&sd->min_limit);
1249 // validate curr_time and max_limt according to the min_limit
1250 _validate_datetime_limits(&sd->max_limit, &sd->min_limit, EINA_FALSE);
1251 _validate_datetime_limits(&sd->curr_time, &sd->min_limit, EINA_FALSE);
1252 _apply_field_limits(obj);
1254 if (!_date_cmp(&old_time, &sd->curr_time))
1255 eo_do(obj, eo_event_callback_call(ELM_DATETIME_EVENT_CHANGED, NULL));
1260 EOLIAN static Eina_Bool
1261 _elm_datetime_value_max_get(const Eo *obj EINA_UNUSED, Elm_Datetime_Data *sd, struct tm *maxtime)
1263 EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE);
1265 *maxtime = sd->max_limit;
1269 EOLIAN static Eina_Bool
1270 _elm_datetime_value_max_set(Eo *obj, Elm_Datetime_Data *sd, const struct tm *maxtime)
1274 EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE);
1276 if (_date_cmp(&sd->max_limit, maxtime)) return EINA_TRUE;
1277 sd->max_limit = *maxtime;
1278 old_time = sd->curr_time;
1279 // apply default field restrictions for max_limit
1280 _apply_range_restrictions(&sd->max_limit);
1281 // validate curr_time and min_limt according to the max_limit
1282 _validate_datetime_limits(&sd->max_limit, &sd->min_limit, EINA_TRUE);
1283 _validate_datetime_limits(&sd->max_limit, &sd->curr_time, EINA_TRUE);
1284 _apply_field_limits(obj);
1286 if (!_date_cmp(&old_time, &sd->curr_time))
1287 eo_do(obj, eo_event_callback_call(ELM_DATETIME_EVENT_CHANGED, NULL));
1293 _elm_datetime_class_constructor(Eo_Class *klass)
1295 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1298 #include "elm_datetime.eo.c"