524e5d3a523bd235f67af4ee967485272e9b5d1c
[framework/uifw/elementary.git] / src / lib / elm_datefield.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include <langinfo.h>
4
5 /**
6  * @defgroup Datefield Datefield
7  * @ingroup Elementary
8  *
9  * This is a date editfield. it is used to input date and time using keypad
10  */
11
12 typedef struct _Widget_Data Widget_Data;
13
14 enum 
15 {
16   DATE_YEAR,
17   DATE_MON,
18   DATE_DAY,
19   DATE_MAX
20 };
21
22 enum
23 {
24   TIME_HOUR,
25   TIME_MIN,
26   TIME_MAX
27 };
28
29 enum
30 {
31   DATE_FORMAT_YYMMDD,
32   DATE_FORMAT_YYDDMM,
33   DATE_FORMAT_MMYYDD,
34   DATE_FORMAT_MMDDYY,
35   DATE_FORMAT_DDYYMM,
36   DATE_FORMAT_DDMMYY,
37   DATE_FORMAT_MAX
38 };
39
40 #define YEAR_MAX_LENGTH 4
41 #define DAY_MAX_LENGTH 2
42 #define TIME_MAX_LENGTH 2
43
44 #define MONTH_MAXIMUM 12
45 #define HOUR_24H_MAXIMUM 23
46 #define HOUR_12H_MAXIMUM 12
47 #define MIN_MAXIMUM 59
48
49 struct _Widget_Data
50 {
51    Evas_Object *base;
52    Evas_Object *date[DATE_MAX];
53    Evas_Object *time[TIME_MAX];
54    Ecore_Event_Handler *handler;
55    Ecore_Idler *idler;
56    int layout;
57
58    int year, month, day, hour, min;
59    int y_max, m_max, d_max;
60    int y_min, m_min, d_min;
61    int date_format;
62    Eina_Bool pm:1;
63    Eina_Bool time_mode:1;
64    Eina_Bool format_exists:1;
65    Eina_Bool editing:1;
66
67    void (*func)(void *data, Evas_Object *obj, int value);
68    void *func_data;
69 };
70
71 static const char *widtype = NULL;
72
73 static void _del_hook(Evas_Object *obj);
74 static void _theme_hook(Evas_Object *obj);
75 static void _sizing_eval(Evas_Object *obj);
76 static void _on_focus_hook(void *data, Evas_Object *obj);
77
78 static void _signal_rect_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source);
79 static void _signal_ampm_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source);
80 static void _signal_ampm_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
81 static void _entry_focused_cb(void *data, Evas_Object *obj, void *event_info);
82 static void _entry_unfocused_cb(void *data, Evas_Object *obj, void *event_info);
83 static void _entry_key_up_cb(void *data, Evas *e , Evas_Object *obj , void *event_info);
84 static Eina_Bool _imf_event_commit_cb(void *data, int type, void *event);
85 static void _input_panel_event_callback(void *data, Ecore_IMF_Context *ctx, int value);
86
87 static void _date_entry_add(Evas_Object *obj);
88 static void _time_entry_add(Evas_Object *obj);
89 static void _date_update(Evas_Object *obj);
90 static Eina_Bool _focus_idler_cb(void *obj);
91 static void _entry_focus_move(Evas_Object *obj, Evas_Object *focus_obj);
92 static Eina_Bool _check_input_done(Evas_Object *obj, Evas_Object *focus_obj, int strlen);
93 static char* _get_i18n_string(Evas_Object *obj, nl_item item);
94 static int _maximum_day_get(int year, int month);
95 static int _check_date_boundary(Evas_Object *obj, int num, int flag);
96
97 static void
98 _del_hook(Evas_Object *obj)
99 {
100    Widget_Data *wd = elm_widget_data_get(obj);
101    if (!wd) return ;
102
103    ecore_event_handler_del(wd->handler);
104
105    free(wd);
106 }
107
108 static void
109 _on_focus_hook(void *data, Evas_Object *obj)
110 {
111    Widget_Data *wd = elm_widget_data_get(obj);
112    if (!wd || !wd->base) return ;
113
114    if (elm_widget_focus_get(obj)) wd->idler = ecore_idler_add(_focus_idler_cb, obj);
115 }
116
117 static void
118 _theme_hook(Evas_Object *obj)
119 {
120    Widget_Data *wd = elm_widget_data_get(obj);
121    char sig[32] = {0,};
122    int i;
123
124    if (!wd || !wd->base) return;
125
126    if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
127      {
128         _elm_theme_object_set(obj, wd->base, "datefield", "dateandtime", elm_widget_style_get(obj));
129
130         for (i = 0; i < DATE_MAX; i++)
131           elm_object_style_set(wd->date[i], "datefield/hybrid");
132         for (i = 0; i < TIME_MAX; i++)
133           elm_object_style_set(wd->time[i], "datefield/hybrid");
134      }
135    else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
136      {
137         _elm_theme_object_set(obj, wd->base, "datefield", "date", elm_widget_style_get(obj));
138
139         for (i = 0; i < DATE_MAX; i++)
140           elm_object_style_set(wd->date[i], "datefield");
141
142         for (i = 0; i < TIME_MAX; i++)
143           evas_object_hide(wd->time[i]);
144      }
145    else if (wd->layout == ELM_DATEFIELD_LAYOUT_TIME)
146      {
147         _elm_theme_object_set(obj, wd->base, "datefield", "time", elm_widget_style_get(obj));
148
149         for (i = 0; i < TIME_MAX; i++)
150           elm_object_style_set(wd->time[i], "datefield");
151
152         for (i = 0; i < DATE_MAX; i++)
153           evas_object_hide(wd->date[i]);
154      }
155
156    if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME || wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
157      {
158         edje_object_part_swallow(wd->base, "elm.swallow.date.year", wd->date[DATE_YEAR]);
159         edje_object_part_swallow(wd->base, "elm.swallow.date.month", wd->date[DATE_MON]);
160         edje_object_part_swallow(wd->base, "elm.swallow.date.day", wd->date[DATE_DAY]);
161         edje_object_part_text_set(wd->base, "elm.text.date.comma", ",");
162      }
163
164    if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME || wd->layout == ELM_DATEFIELD_LAYOUT_TIME)
165      {
166         edje_object_part_swallow(wd->base, "elm.swallow.time.hour", wd->time[TIME_HOUR]);
167         edje_object_part_swallow(wd->base, "elm.swallow.time.min", wd->time[TIME_MIN]);
168         edje_object_part_text_set(wd->base, "elm.text.colon", ":");
169      }
170
171    edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
172
173    //set date format
174    if (wd->format_exists)
175       sprintf(sig, "elm,state,format,%s", elm_datefield_date_format_get(obj));
176    else
177      {
178         char *str = _get_i18n_string(obj, D_FMT);
179         if (str) 
180           {
181              if (!strcmp(str, "yymmdd")) wd->date_format = DATE_FORMAT_YYMMDD;
182              else if (!strcmp(str, "yyddmm")) wd->date_format = DATE_FORMAT_YYDDMM;
183              else if (!strcmp(str, "mmyydd")) wd->date_format = DATE_FORMAT_MMYYDD;
184              else if (!strcmp(str, "mmddyy")) wd->date_format = DATE_FORMAT_MMDDYY;
185              else if (!strcmp(str, "ddyymm")) wd->date_format = DATE_FORMAT_DDYYMM;
186              else if (!strcmp(str, "ddmmyy")) wd->date_format = DATE_FORMAT_DDMMYY;
187              sprintf(sig, "elm,state,format,%s",str);
188              free(str);
189           }
190      }
191    edje_object_signal_emit(wd->base, sig, "elm");
192
193    _date_update(obj);
194    _sizing_eval(obj);
195 }
196
197 static void
198 _sizing_eval(Evas_Object *obj)
199 {
200    Widget_Data *wd = elm_widget_data_get(obj);
201    Evas_Coord minw = -1, minh = -1;
202
203    edje_object_size_min_calc(wd->base, &minw, &minh);
204    evas_object_size_hint_min_set(obj, minw, minh);
205    evas_object_size_hint_max_set(obj, -1, -1);
206 }
207
208 static void
209 _signal_ampm_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source)
210 {
211    Widget_Data *wd = elm_widget_data_get(data);
212    Evas_Object *focus_obj;
213
214    if (!wd || !wd->base) return ;
215
216    focus_obj = elm_widget_focused_object_get(data);
217    if (focus_obj) elm_object_unfocus(focus_obj);
218 }
219
220 static void
221 _signal_ampm_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
222 {
223    Widget_Data *wd = elm_widget_data_get(data);
224    char *str;
225
226    if (!wd || !wd->base) return ;
227
228    wd->pm = !wd->pm; 
229    if (wd->pm)
230      {
231         str = _get_i18n_string(data, PM_STR);
232         if (str) 
233           {
234              edje_object_part_text_set(wd->base, "elm.text.ampm", str);
235              free(str);
236           }
237         wd->hour += HOUR_12H_MAXIMUM;
238      }
239    else
240      {
241         str = _get_i18n_string(data, AM_STR);
242         if (str)
243           {
244              edje_object_part_text_set(wd->base, "elm.text.ampm", str);
245              free(str);
246           }
247         wd->hour -= HOUR_12H_MAXIMUM;
248      }
249    evas_object_smart_callback_call(data, "changed", NULL);
250 }
251
252 static void
253 _signal_rect_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source)
254 {
255    Widget_Data *wd = elm_widget_data_get(data);
256    if (!wd) return;
257
258    if (!strcmp(source, "elm.rect.date.year.over"))
259      elm_object_focus(wd->date[DATE_YEAR]);
260    else if (!strcmp(source, "elm.rect.date.month.over"))
261      elm_object_focus(wd->date[DATE_MON]);
262    else if (!strcmp(source, "elm.rect.date.day.over"))
263      elm_object_focus(wd->date[DATE_DAY]);
264    else if (!strcmp(source, "elm.rect.time.hour.over"))
265      elm_object_focus(wd->time[TIME_HOUR]);
266    else if (!strcmp(source, "elm.rect.time.min.over"))
267      elm_object_focus(wd->time[TIME_MIN]);
268    else if (!strcmp(source, "elm.rect.date.left.pad"))
269      {
270         switch (wd->date_format)
271           {
272            case DATE_FORMAT_YYDDMM:
273            case DATE_FORMAT_YYMMDD:
274              elm_object_focus(wd->date[DATE_YEAR]);
275              break;
276            case DATE_FORMAT_MMDDYY:
277            case DATE_FORMAT_MMYYDD:
278              elm_object_focus(wd->date[DATE_MON]);
279              break;
280            case DATE_FORMAT_DDMMYY:
281            case DATE_FORMAT_DDYYMM:
282              elm_object_focus(wd->date[DATE_DAY]);
283           }
284      }
285    else if (!strcmp(source, "elm.rect.date.right.pad"))
286      {
287         switch (wd->date_format)
288           {
289            case DATE_FORMAT_MMDDYY:
290            case DATE_FORMAT_DDMMYY:
291              elm_object_focus(wd->date[DATE_YEAR]);
292              break;
293            case DATE_FORMAT_DDYYMM:
294            case DATE_FORMAT_YYDDMM:
295              elm_object_focus(wd->date[DATE_MON]);
296              break;
297            case DATE_FORMAT_YYMMDD:
298            case DATE_FORMAT_MMYYDD:
299              elm_object_focus(wd->date[DATE_DAY]);
300           }
301      }
302 }
303
304 static Eina_Bool 
305 _focus_idler_cb(void *obj)
306 {
307    Widget_Data *wd = elm_widget_data_get(obj);
308    Evas_Object *focus_obj;
309
310    focus_obj = elm_widget_focused_object_get(obj);
311    if (focus_obj == obj)
312      {
313         if (wd->layout == ELM_DATEFIELD_LAYOUT_TIME)
314           elm_object_focus(wd->time[TIME_HOUR]);
315
316         else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME || wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
317           {
318              switch (wd->date_format)
319                {
320                 case DATE_FORMAT_YYDDMM:
321                 case DATE_FORMAT_YYMMDD:
322                   elm_object_focus(wd->date[DATE_YEAR]);
323                   break;
324                 case DATE_FORMAT_MMDDYY:
325                 case DATE_FORMAT_MMYYDD:
326                   elm_object_focus(wd->date[DATE_MON]);
327                   break;
328                 case DATE_FORMAT_DDMMYY:
329                 case DATE_FORMAT_DDYYMM:
330                   elm_object_focus(wd->date[DATE_DAY]);
331                }
332           }
333      }
334    wd->idler = NULL;
335    return EINA_FALSE;
336 }
337
338 static void
339 _entry_focused_cb(void *data, Evas_Object *obj, void *event_info)
340 {
341    Widget_Data *wd = elm_widget_data_get(data);
342    if (!wd || !wd->base) return;
343
344    if (wd->idler) 
345      {
346         ecore_idler_del(wd->idler);
347         wd->idler = NULL;
348      }
349
350    if (obj == wd->date[DATE_YEAR])
351      edje_object_signal_emit(wd->base, "elm,state,year,focus,in", "elm");
352    else if (obj == wd->date[DATE_MON])
353      edje_object_signal_emit(wd->base, "elm,state,month,focus,in", "elm");
354    else if (obj == wd->date[DATE_DAY])
355      edje_object_signal_emit(wd->base, "elm,state,day,focus,in", "elm");
356    else if (obj == wd->time[TIME_HOUR])
357      edje_object_signal_emit(wd->base, "elm,state,hour,focus,in", "elm");
358    else if (obj == wd->time[TIME_MIN])
359      edje_object_signal_emit(wd->base, "elm,state,min,focus,in", "elm");
360 }
361
362 static void
363 _entry_unfocused_cb(void *data, Evas_Object *obj, void *event_info)
364 {
365    Widget_Data *wd = elm_widget_data_get(data);
366    char str[YEAR_MAX_LENGTH+1] = {0,};
367    char *i18n_str;
368    int num = 0;
369
370    if (!wd || !wd->base) return;
371    wd->editing = FALSE;
372
373    if (obj == wd->date[DATE_YEAR])
374      {
375         if (strlen(elm_entry_entry_get(wd->date[DATE_YEAR])))
376           wd->year = atoi(elm_entry_entry_get(wd->date[DATE_YEAR]));
377         wd->year = _check_date_boundary(data, wd->year, DATE_YEAR);
378         sprintf(str, "%d", wd->year);
379         elm_entry_entry_set(wd->date[DATE_YEAR], str);
380         //check month boundary
381         if (wd->month != (num = _check_date_boundary(data, wd->month, DATE_MON)))
382           {
383              wd->month = num;
384              i18n_str = _get_i18n_string(obj, ABMON_1+wd->month-1);
385              if (i18n_str)
386                {
387                   elm_entry_entry_set(wd->date[DATE_MON], i18n_str);
388                   free(i18n_str);
389                }
390           }
391         //check day boundary
392         if (wd->day != (num = _check_date_boundary(data, wd->day, DATE_DAY)))
393           {
394              wd->day = num;
395              sprintf(str, "%d", wd->day);
396              elm_entry_entry_set(wd->date[DATE_DAY], str);
397           }
398         edje_object_signal_emit(wd->base, "elm,state,year,focus,out", "elm");
399      }
400    else if (obj == wd->date[DATE_MON])
401      {
402         if (wd->month != (num = _check_date_boundary(data, wd->month, DATE_MON)))
403           {
404              wd->month = num;
405              i18n_str = _get_i18n_string(obj, ABMON_1+wd->month-1);
406              if (i18n_str)
407                {
408                   elm_entry_entry_set(wd->date[DATE_MON], i18n_str);
409                   free(i18n_str);
410                }  
411           }
412         //check day boundary
413         if (wd->day != (num = _check_date_boundary(data, wd->day, DATE_DAY)))
414           {
415              wd->day = num;
416              sprintf(str, "%d", wd->day);               
417              elm_entry_entry_set(wd->date[DATE_DAY], str);
418           }
419         edje_object_signal_emit(wd->base, "elm,state,month,focus,out", "elm");
420      }
421    else if (obj == wd->date[DATE_DAY])
422      {
423         if (strlen(elm_entry_entry_get(wd->date[DATE_DAY])))
424           wd->day = atoi(elm_entry_entry_get(wd->date[DATE_DAY]));
425         wd->day = _check_date_boundary(data, wd->day, DATE_DAY);
426         sprintf(str, "%d", wd->day);
427         elm_entry_entry_set(wd->date[DATE_DAY], str);
428         edje_object_signal_emit(wd->base, "elm,state,day,focus,out", "elm");
429      }
430    else if (obj == wd->time[TIME_HOUR])
431      {
432         if (strlen(elm_entry_entry_get(wd->time[TIME_HOUR])))
433           num = atoi(elm_entry_entry_get(wd->time[TIME_HOUR]));
434         else num = wd->hour;
435
436         if (!wd->time_mode) // 24 mode
437           {
438              if (num > HOUR_24H_MAXIMUM) num = HOUR_24H_MAXIMUM;
439              wd->hour = num;
440           }
441         else // 12 mode
442           {
443              if (num > HOUR_24H_MAXIMUM || num == 0)
444                {
445                   num = HOUR_12H_MAXIMUM;
446                   wd->pm = EINA_FALSE;
447                }
448              else if (num > HOUR_12H_MAXIMUM)
449                {
450                   num -= HOUR_12H_MAXIMUM;
451                   wd->pm = EINA_TRUE;
452                }
453              wd->hour = (wd->pm == EINA_TRUE)? num + HOUR_12H_MAXIMUM : num;
454              if ((wd->hour % 12) == 0) wd->hour -= HOUR_12H_MAXIMUM;
455              if (wd->pm) 
456                {
457                   i18n_str = _get_i18n_string(data, PM_STR);
458                   if (i18n_str)
459                     {
460                        edje_object_part_text_set(wd->base, "elm.text.ampm", i18n_str);
461                        free(i18n_str);
462                     }
463                }
464              else 
465                {
466                   i18n_str = _get_i18n_string(data, AM_STR);
467                   if (i18n_str)
468                     {
469                        edje_object_part_text_set(wd->base, "elm.text.ampm", i18n_str);
470                        free(i18n_str);
471                     }
472                }
473           }
474         sprintf(str, "%02d", num);
475         elm_entry_entry_set(wd->time[TIME_HOUR], str);
476         edje_object_signal_emit(wd->base, "elm,state,hour,focus,out", "elm");
477      }
478    else if (obj == wd->time[TIME_MIN])
479      {
480         if (strlen(elm_entry_entry_get(wd->time[TIME_MIN]))) 
481           wd->min = atoi(elm_entry_entry_get(wd->time[TIME_MIN]));
482         if (wd->min > MIN_MAXIMUM) wd->min = MIN_MAXIMUM;
483
484         sprintf(str, "%02d", wd->min);
485         elm_entry_entry_set(wd->time[TIME_MIN], str);
486         edje_object_signal_emit(wd->base, "elm,state,min,focus,out", "elm");
487      }
488    evas_object_smart_callback_call(data, "changed", NULL);
489 }
490
491 static void 
492 _entry_focus_move(Evas_Object *obj, Evas_Object *focus_obj)
493 {
494    Widget_Data *wd = elm_widget_data_get(obj);
495    if (!wd) return;
496
497    if (focus_obj == wd->date[DATE_YEAR])
498      {
499         switch (wd->date_format)
500           {
501            case DATE_FORMAT_DDMMYY:
502            case DATE_FORMAT_MMDDYY:
503              {
504                  if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
505                    elm_object_focus(wd->time[TIME_HOUR]);
506                  else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
507                    elm_object_unfocus(wd->date[DATE_YEAR]);
508              }
509              break;
510            case DATE_FORMAT_DDYYMM:
511            case DATE_FORMAT_YYMMDD:
512              elm_object_focus(wd->date[DATE_MON]);
513              break;
514            case DATE_FORMAT_MMYYDD:
515            case DATE_FORMAT_YYDDMM:
516              elm_object_focus(wd->date[DATE_DAY]);
517           }
518      }
519    else if (focus_obj == wd->date[DATE_MON])
520      {
521         switch (wd->date_format)
522           {
523            case DATE_FORMAT_DDYYMM:
524            case DATE_FORMAT_YYDDMM:
525              {
526                 if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
527                   elm_object_focus(wd->time[TIME_HOUR]);
528                 else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
529                   elm_object_unfocus(wd->date[DATE_MON]);
530              }
531              break;
532            case DATE_FORMAT_DDMMYY:
533            case DATE_FORMAT_MMYYDD:
534              elm_object_focus(wd->date[DATE_YEAR]);
535              break;
536            case DATE_FORMAT_MMDDYY:
537            case DATE_FORMAT_YYMMDD:
538              elm_object_focus(wd->date[DATE_DAY]);
539           }
540      }
541    else if (focus_obj == wd->date[DATE_DAY])
542      {
543         switch (wd->date_format)
544           {
545            case DATE_FORMAT_YYMMDD:
546            case DATE_FORMAT_MMYYDD:
547              {
548                 if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
549                   elm_object_focus(wd->time[TIME_HOUR]);
550                 else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
551                   elm_object_unfocus(wd->date[DATE_DAY]);
552              }
553              break;
554            case DATE_FORMAT_DDYYMM:
555            case DATE_FORMAT_MMDDYY:
556              elm_object_focus(wd->date[DATE_YEAR]);
557              break;
558            case DATE_FORMAT_DDMMYY:
559            case DATE_FORMAT_YYDDMM:
560              elm_object_focus(wd->date[DATE_MON]);
561           }
562      }
563    else if (focus_obj == wd->time[TIME_HOUR])
564      elm_object_focus(wd->time[TIME_MIN]);
565    else if (focus_obj == wd->time[TIME_MIN])
566      elm_object_unfocus(wd->time[TIME_MIN]);
567 }
568
569 static int
570 _check_date_boundary(Evas_Object *obj, int num, int flag)
571 {
572    Widget_Data *wd = elm_widget_data_get(obj);
573    if (flag == DATE_YEAR)
574      {
575         if (num > wd->y_max) num = wd->y_max;
576         else if (num < wd->y_min) num = wd->y_min;
577         return num;
578      }
579
580    else if (flag == DATE_MON)
581      {
582         if (wd->year == wd->y_max && num > wd->m_max) num = wd->m_max;
583         else if (wd->year == wd->y_min && num < wd->m_min) num = wd->m_min;
584         else if (num > MONTH_MAXIMUM) num = MONTH_MAXIMUM;
585         else if (num <= 0) num = 1;
586         return num;
587      }
588
589    else if (flag == DATE_DAY)
590      {
591         int day_of_month = _maximum_day_get(wd->year, wd->month);
592         if (wd->year == wd->y_max && wd->month == wd->m_max && num > wd->d_max) num = wd->d_max;
593         else if (wd->year == wd->y_min && wd->month == wd->m_min && num < wd->d_min) num = wd->d_min;
594         else if (num > day_of_month) num = day_of_month;
595         else if (num <= 0) num = 1;
596         return num;
597      }
598    return num;
599 }
600
601 static char*
602 _get_i18n_string(Evas_Object *obj, nl_item item)
603 {
604    Widget_Data *wd = elm_widget_data_get(obj);
605    const char *fmt;
606    char *str = NULL;
607    int i = 0, j = 0;
608
609    if (!wd) return NULL;
610
611    fmt = nl_langinfo(item);
612    if (!fmt) return NULL;
613
614    switch (item)
615      {
616       case D_FMT:
617          str = calloc(7, sizeof(char));
618          while (fmt[i]) 
619            {
620               if (fmt[i] == '%' && fmt[i+1]) 
621                 {
622                    i++;
623                    switch (fmt[i]) 
624                      {
625                       case 'Y': case 'M': case 'D': case 'y': case 'm': case 'd':
626                          str[j++] = tolower(fmt[i]);
627                          str[j++] = tolower(fmt[i]);
628                          break;
629                      }
630                 }
631               i++;
632            }
633          return str;
634       case AM_STR: 
635       case PM_STR:
636          if (strlen(fmt) > 0)
637            {
638               str = calloc(strlen(fmt)+1, sizeof(char));
639               strcpy(str, fmt);
640            }
641          else
642            {
643               str = calloc(3, sizeof(char));
644               if (item == AM_STR) strcpy(str, "AM");
645               else if (item == PM_STR) strcpy(str, "PM");
646            }
647          return str;
648       case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4: case ABMON_5: case ABMON_6:
649       case ABMON_7: case ABMON_8: case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12:
650          str = calloc(strlen(fmt)+1, sizeof(char));
651          while (fmt[i])
652            {
653               str[j++] = fmt[i];
654               if (fmt[i] >= '1' && fmt[i] <= '9')
655                 {
656                    if (fmt[i+1] >= '1' && fmt[i+1] <= '9')
657                       str[j] = fmt[i+1];
658                    break;
659                 }
660               i++;
661            }
662          return str;     
663      }
664    return NULL;
665 }
666
667 static int
668 _maximum_day_get(int year, int month)
669 {
670    int day_of_month = 0;
671    if (year == 0 || month == 0) return 0;
672
673    switch (month)
674      {
675       case 4:
676       case 6:
677       case 9:
678       case 11:
679         day_of_month = 30;
680         break;
681       case 2:
682         {
683            if ((!(year % 4) && (year % 100)) || !(year % 400))
684              day_of_month = 29;
685            else
686              day_of_month = 28;
687         }
688         break;
689       default:
690         day_of_month = 31;
691         break;
692      }
693
694    return day_of_month;
695 }
696
697 static Eina_Bool 
698 _check_input_done(Evas_Object *obj, Evas_Object *focus_obj, int strlen)
699 {
700    Widget_Data *wd = elm_widget_data_get(obj);
701
702    if (!wd) return EINA_FALSE;
703
704    if (focus_obj == wd->date[DATE_YEAR] && strlen == YEAR_MAX_LENGTH)
705      wd->editing = EINA_FALSE;
706    else if (focus_obj == wd->date[DATE_MON])
707      wd->editing = EINA_FALSE;
708    else if (focus_obj == wd->date[DATE_DAY])
709      {
710         if (strlen == DAY_MAX_LENGTH || atoi(elm_entry_entry_get(focus_obj)) > 3)
711           wd->editing = EINA_FALSE;
712      }
713    else if (focus_obj == wd->time[TIME_HOUR])
714      {
715         if (strlen == TIME_MAX_LENGTH || atoi(elm_entry_entry_get(focus_obj)) > 2)
716           wd->editing = EINA_FALSE;
717      }
718    else if (focus_obj == wd->time[TIME_MIN])
719      {
720         if (strlen == TIME_MAX_LENGTH || atoi(elm_entry_entry_get(focus_obj)) > 5) 
721           wd->editing = EINA_FALSE;
722      }
723    return !wd->editing;
724 }
725
726 static void
727 _entry_key_up_cb(void *data, Evas *e , Evas_Object *obj , void *event_info)
728 {
729    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *) event_info;
730
731    if (!strcmp(ev->keyname, "BackSpace"))
732      elm_entry_entry_set(obj, "");
733 }
734
735 static Eina_Bool 
736 _imf_event_commit_cb(void *data, int type, void *event)
737 {
738    Widget_Data *wd = elm_widget_data_get(data);
739    Ecore_IMF_Event_Commit *ev = (Ecore_IMF_Event_Commit *) event;
740    Evas_Object *focus_obj;
741    char str[YEAR_MAX_LENGTH+1] = {0,};
742
743    if (!wd) return ECORE_CALLBACK_PASS_ON;
744    if (!elm_widget_focus_get(data)) return ECORE_CALLBACK_PASS_ON;
745
746    focus_obj = elm_widget_focused_object_get(data);
747    if (!wd->editing) 
748      {
749         elm_entry_entry_set(focus_obj, "");
750         wd->editing = EINA_TRUE;
751      }
752    if (focus_obj == wd->date[DATE_MON])
753      {
754         char *i18n_str;
755         wd->month = atoi(ev->str);
756         i18n_str = _get_i18n_string(data, ABMON_1+wd->month-1);
757         if (i18n_str)
758           {
759              elm_entry_entry_set(focus_obj, i18n_str);
760              free(i18n_str);
761           }
762      }
763    else
764      {
765         strcpy(str, elm_entry_entry_get(focus_obj));
766         str[strlen(str)] = ev->str[0];
767         elm_entry_entry_set(focus_obj, str);
768      }
769
770    if (_check_input_done(data, focus_obj, strlen(str)))
771      _entry_focus_move(data, focus_obj);
772
773    return ECORE_CALLBACK_DONE;
774 }
775
776 static void 
777 _input_panel_event_callback(void *data, Ecore_IMF_Context *ctx, int value)
778 {
779    Widget_Data *wd = elm_widget_data_get(data);
780
781    if (!wd) return;
782
783    if (wd->func)  
784      wd->func(wd->func_data, data, value);
785 }
786
787 static void
788 _date_update(Evas_Object *obj)
789 {
790    Widget_Data *wd = elm_widget_data_get(obj);
791    char str[YEAR_MAX_LENGTH+1] = {0,};
792    char *i18n_str;
793
794    if (!wd || !wd->base) return;
795
796    sprintf(str, "%d", wd->year);
797    elm_entry_entry_set(wd->date[DATE_YEAR], str);
798
799    i18n_str = _get_i18n_string(obj, ABMON_1+wd->month-1);
800    if (i18n_str)
801      {
802         elm_entry_entry_set(wd->date[DATE_MON], i18n_str);
803         free(i18n_str);
804      }
805
806    sprintf(str, "%d", wd->day);
807    elm_entry_entry_set(wd->date[DATE_DAY], str);
808
809    if (!wd->time_mode) //24 mode
810      sprintf(str, "%d", wd->hour);
811    else
812      {
813         if (wd->hour >= HOUR_12H_MAXIMUM)
814           {
815              wd->pm = EINA_TRUE;
816              i18n_str = _get_i18n_string(obj, PM_STR);
817              if (i18n_str) 
818                {
819                   edje_object_part_text_set(wd->base, "elm.text.ampm", i18n_str);
820                   free(i18n_str);
821                }
822           }
823         else
824           {
825              wd->pm = EINA_FALSE;
826              i18n_str = _get_i18n_string(obj, AM_STR);
827              if (i18n_str)
828                {
829                   edje_object_part_text_set(wd->base, "elm.text.ampm", i18n_str);               
830                   free(i18n_str);
831                }
832           }
833
834         if (wd->hour > HOUR_12H_MAXIMUM)
835            sprintf(str, "%02d", wd->hour - HOUR_12H_MAXIMUM);
836         else if (wd->hour == 0)
837            sprintf(str, "%02d", HOUR_12H_MAXIMUM);
838         else
839            sprintf(str, "%02d", wd->hour);
840      }
841    elm_entry_entry_set(wd->time[TIME_HOUR], str);
842    sprintf(str, "%02d", wd->min);
843    elm_entry_entry_set(wd->time[TIME_MIN], str);
844 }
845
846 static void 
847 _date_entry_add(Evas_Object *obj)
848 {
849    Widget_Data *wd = elm_widget_data_get(obj);
850    int i;
851
852    if (!wd) return;     
853
854    for (i = 0; i < DATE_MAX; i++)
855      {
856         wd->date[i] = elm_entry_add(obj);
857         elm_entry_single_line_set(wd->date[i], EINA_TRUE);
858         elm_entry_context_menu_disabled_set(wd->date[i], EINA_TRUE);
859         if (i == DATE_MON) elm_entry_input_panel_layout_set(wd->date[i], ELM_INPUT_PANEL_LAYOUT_MONTH);
860         else elm_entry_input_panel_layout_set(wd->date[i], ELM_INPUT_PANEL_LAYOUT_NUMBERONLY);
861         evas_object_size_hint_weight_set(wd->date[i], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
862         evas_object_size_hint_align_set(wd->date[i], EVAS_HINT_FILL, EVAS_HINT_FILL);
863         evas_object_smart_callback_add(wd->date[i], "focused", _entry_focused_cb, obj);
864         evas_object_smart_callback_add(wd->date[i], "unfocused", _entry_unfocused_cb, obj);
865         evas_object_event_callback_add(wd->date[i], EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
866         elm_widget_sub_object_add(obj, wd->date[i]);
867      }
868    elm_entry_maximum_bytes_set(wd->date[DATE_YEAR], YEAR_MAX_LENGTH);
869    elm_entry_maximum_bytes_set(wd->date[DATE_DAY], DAY_MAX_LENGTH);
870 }
871
872 static void 
873 _time_entry_add(Evas_Object *obj)
874 {
875    Widget_Data *wd = elm_widget_data_get(obj);
876    int i;
877
878    if (!wd) return;
879
880    for (i = 0; i < TIME_MAX; i++)
881      {
882         wd->time[i] = elm_entry_add(obj);
883         elm_entry_single_line_set(wd->time[i], EINA_TRUE);
884         elm_entry_context_menu_disabled_set(wd->time[i], EINA_TRUE);
885         elm_entry_input_panel_layout_set(wd->time[i], ELM_INPUT_PANEL_LAYOUT_NUMBERONLY);
886         elm_entry_maximum_bytes_set(wd->time[i], TIME_MAX_LENGTH);
887         evas_object_size_hint_weight_set(wd->time[i], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
888         evas_object_size_hint_align_set(wd->time[i], EVAS_HINT_FILL, EVAS_HINT_FILL);
889         evas_object_smart_callback_add(wd->time[i], "focused", _entry_focused_cb, obj);
890         evas_object_smart_callback_add(wd->time[i], "unfocused", _entry_unfocused_cb, obj);
891         evas_object_event_callback_add(wd->time[i], EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
892         elm_widget_sub_object_add(obj, wd->time[i]);
893      }
894 }
895
896 /**
897  * Add a new datefield object
898  * The date format and strings are based on current locale
899  *
900  * @param parent The parent object
901  * @return The new object or NULL if it cannot be created
902  *
903  * @ingroup Datefield
904  */
905 EAPI Evas_Object *
906 elm_datefield_add(Evas_Object *parent)
907 {
908    Evas_Object *obj;
909    Evas *e;
910    Widget_Data *wd;
911
912    e = evas_object_evas_get(parent);
913    if (!e) return NULL; 
914    wd = ELM_NEW(Widget_Data);
915    obj = elm_widget_add(e); 
916    ELM_SET_WIDTYPE(widtype, "datefield");
917    elm_widget_type_set(obj, "datefield");
918    elm_widget_sub_object_add(parent, obj);
919    elm_widget_data_set(obj, wd);
920    elm_widget_del_hook_set(obj, _del_hook);
921    elm_widget_theme_hook_set(obj, _theme_hook);
922    elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL );
923    elm_widget_can_focus_set(obj, EINA_TRUE);
924
925    wd->base = edje_object_add(e);
926    elm_widget_resize_object_set(obj, wd->base);
927    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.left.pad", _signal_rect_mouse_down, obj);
928    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.year.over", _signal_rect_mouse_down, obj);
929    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.month.over", _signal_rect_mouse_down, obj);
930    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.day.over", _signal_rect_mouse_down, obj);
931    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.right.pad", _signal_rect_mouse_down, obj);
932
933    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.hour.over", _signal_rect_mouse_down, obj);
934    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.min.over", _signal_rect_mouse_down, obj);
935    edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.ampm.over", _signal_ampm_mouse_down, obj);
936    edje_object_signal_callback_add(wd->base, "mouse,clicked,1", "elm.rect.time.ampm.over", _signal_ampm_clicked, obj);
937
938    wd->handler =  ecore_event_handler_add(ECORE_IMF_EVENT_COMMIT, _imf_event_commit_cb, obj);
939    _date_entry_add(obj);
940    _time_entry_add(obj);
941
942    wd->y_min = 1900;
943    wd->m_min = 1;
944    wd->d_min = 1;
945    wd->y_max = 2099;
946    wd->m_max = 12;
947    wd->d_max = 31;
948    wd->year = wd->y_min;
949    wd->month = 1;
950    wd->day = 1;
951
952    wd->layout = ELM_DATEFIELD_LAYOUT_DATEANDTIME;
953    wd->time_mode = EINA_TRUE;
954
955    _theme_hook(obj);
956
957    return obj;
958 }
959
960 /**
961  * set layout for the datefield
962  *
963  * @param obj The datefield object
964  * @param layout set layout for date/time/dateandtime (default: ELM_DATEFIELD_LAYOUT_DATEANDTIME)
965  *
966  * @ingroup Datefield
967  */
968 EAPI void
969 elm_datefield_layout_set(Evas_Object *obj, Elm_Datefield_Layout layout)
970 {
971    ELM_CHECK_WIDTYPE(obj, widtype);
972    Widget_Data *wd = elm_widget_data_get(obj);
973
974    if (!wd) return;
975    if (layout < ELM_DATEFIELD_LAYOUT_TIME ||layout > ELM_DATEFIELD_LAYOUT_DATEANDTIME) return;
976
977    if (wd->layout != layout)
978      {
979         wd->layout = layout;
980         _theme_hook(obj);
981      }
982    return;
983 }
984
985 /**
986  * get layout of the datefield
987  *
988  * @param obj The datefield object
989  * @return layout of the datefield
990  *
991  * @ingroup Datefield
992  */
993 EAPI Elm_Datefield_Layout
994 elm_datefield_layout_get(const Evas_Object *obj)
995 {
996    ELM_CHECK_WIDTYPE(obj, widtype) 0;
997    Widget_Data *wd = elm_widget_data_get(obj);
998
999    if (!wd) return 0;
1000
1001    return wd->layout;
1002 }
1003
1004 /**
1005  * Set selected date of the datefield
1006  *
1007  * @param obj The datefield object
1008  * @param year The year to set
1009  * @param month The month to set
1010  * @param day The day to set
1011  * @param hour The hours to set (24hour mode - 0~23)
1012  * @param min The minutes to set (0~59)
1013  * 
1014  * @ingroup Datefield
1015  */
1016 EAPI void
1017 elm_datefield_date_set(Evas_Object *obj, int year, int month, int day, int hour, int min)
1018 {
1019    ELM_CHECK_WIDTYPE(obj, widtype);
1020    Widget_Data *wd = elm_widget_data_get(obj);
1021
1022    if (!wd) return;
1023
1024    wd->year = _check_date_boundary(obj, year, DATE_YEAR);
1025    wd->month = _check_date_boundary(obj, month, DATE_MON);
1026    wd->day = _check_date_boundary(obj, day, DATE_DAY);
1027
1028    if (hour > HOUR_24H_MAXIMUM) wd->hour = HOUR_24H_MAXIMUM;
1029    else if (hour < 0) wd->hour = 0;
1030    else wd->hour = hour;
1031
1032    if (min > MIN_MAXIMUM) wd->min = MIN_MAXIMUM;
1033    else if (min < 0) wd->min = 0;
1034    else wd->min = min;
1035
1036    _date_update(obj);
1037 }
1038
1039 /**
1040  * Get selected date of the datefield
1041  *
1042  * @param obj The datefield object
1043  * @param year The pointer to the variable get the selected year
1044  * @param month The pointer to the variable get the selected month
1045  * @param day The pointer to the variable get the selected day
1046  * @param hour The pointer to the variable get the selected hour (24hour mode)
1047  * @param hour The pointer to the variable get the selected min
1048  *
1049  * @ingroup Datefield
1050  */
1051 EAPI void
1052 elm_datefield_date_get(const Evas_Object *obj, int *year, int *month, int *day, int *hour, int *min)
1053 {
1054    ELM_CHECK_WIDTYPE(obj, widtype);
1055    Widget_Data *wd = elm_widget_data_get(obj);
1056
1057    if (!wd) return;
1058
1059    if (year)
1060      *year = wd->year;
1061    if (month)
1062      *month = wd->month;
1063    if (day)
1064      *day = wd->day;
1065    if (hour)
1066      *hour = wd->hour;
1067    if (min)
1068      *min = wd->min;
1069 }
1070
1071 /**
1072  * Set upper boundary of the datefield
1073  *
1074  * @param obj The datefield object
1075  * @param year The year to set
1076  * @param month The month to set
1077  * @param day The day to set
1078  * @return TRUE/FALSE
1079  *
1080  * @ingroup Datefield
1081  */
1082 EAPI Eina_Bool
1083 elm_datefield_date_max_set(Evas_Object *obj, int year, int month, int day)
1084 {
1085    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1086    Widget_Data *wd = elm_widget_data_get(obj);
1087    int day_of_month;
1088    Eina_Bool update = EINA_FALSE;
1089
1090    if (!wd) return EINA_FALSE;
1091    if (month < 1 || month > MONTH_MAXIMUM) return EINA_FALSE;
1092    day_of_month = _maximum_day_get(year, month);
1093    if (day < 1 || day > day_of_month) return EINA_FALSE;
1094
1095    wd->y_max = year;
1096    wd->m_max = month;
1097    wd->d_max = day;
1098
1099    if (wd->year > wd->y_max)
1100      {
1101         wd->year = wd->y_max;
1102         update = EINA_TRUE;
1103      }
1104    if (wd->year == wd->y_max && wd->month > wd->m_max)
1105      {
1106         wd->month = wd->m_max;
1107         update = EINA_TRUE;
1108      }
1109    if (wd->year == wd->y_max && wd->month == wd->m_max && wd->day > wd->d_max)
1110      {
1111         wd->day = wd->d_max;
1112         update = EINA_TRUE;
1113      }
1114
1115    if (update) _date_update(obj);
1116    return EINA_TRUE;
1117 }
1118
1119 /**
1120  * Get upper boundary of the datefield
1121  *
1122  * @param obj The datefield object
1123  * @param year The pointer to the variable get the maximum year
1124  * @param month The pointer to the variable get the maximum month
1125  * @param day The pointer to the variable get the maximum day
1126  *
1127  * @ingroup Datefield
1128  */
1129 EAPI void
1130 elm_datefield_date_max_get(const Evas_Object *obj, int *year, int *month, int *day)
1131 {
1132    ELM_CHECK_WIDTYPE(obj, widtype);
1133    Widget_Data *wd = elm_widget_data_get(obj);
1134
1135    if (!wd) return;
1136
1137    if (year)
1138      *year = wd->y_max;
1139    if (month)
1140      *month = wd->m_max;
1141    if (day)
1142      *day = wd->d_max;
1143 }
1144
1145 /**
1146  * Set lower boundary of the datefield
1147  *
1148  * @param obj The datefield object
1149  * @param year The year to set
1150  * @param month The month to set
1151  * @param day The day to set
1152  * @return TRUE/FALSE
1153  *
1154  * @ingroup Datepicker
1155  */
1156 EAPI Eina_Bool
1157 elm_datefield_date_min_set(Evas_Object *obj, int year, int month, int day)
1158 {
1159    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1160    Widget_Data *wd = elm_widget_data_get(obj);
1161    int day_of_month;
1162    Eina_Bool update = EINA_FALSE;
1163
1164    if (!wd) return EINA_FALSE;
1165    if (month < 1 || month > MONTH_MAXIMUM) return EINA_FALSE;
1166    day_of_month = _maximum_day_get(year, month);
1167    if (day < 1 || day > day_of_month) return EINA_FALSE;
1168
1169    wd->y_min = year;
1170    wd->m_min = month;
1171    wd->d_min = day;
1172
1173    if (wd->year < wd->y_min)
1174      {
1175         wd->year = wd->y_min;
1176         update = EINA_TRUE;
1177      }
1178    if (wd->year == wd->y_min && wd->month < wd->m_min)
1179      {
1180         wd->month = wd->m_min;
1181         update = EINA_TRUE;
1182      }
1183    if (wd->year == wd->y_min && wd->month == wd->m_min && wd->day < wd->d_min)
1184      {
1185         wd->day = wd->d_min;
1186         update = EINA_TRUE;
1187      }
1188
1189    if (update) _date_update(obj);
1190    return EINA_TRUE;
1191 }
1192
1193 /**
1194  * Get lower boundary of the datefield
1195  *
1196  * @param obj The datefield object
1197  * @param year The pointer to the variable get the maximum year
1198  * @param month The pointer to the variable get the maximum month
1199  * @param day The pointer to the variable get the maximum day
1200  *
1201  * @ingroup Datefield
1202  */
1203 EAPI void
1204 elm_datefield_date_min_get(const Evas_Object *obj, int *year, int *month, int *day)
1205 {
1206    ELM_CHECK_WIDTYPE(obj, widtype);
1207    Widget_Data *wd = elm_widget_data_get(obj);
1208
1209    if (!wd) return;
1210
1211    if (year)
1212      *year = wd->y_min;
1213    if (month)
1214      *month = wd->m_min;
1215    if (day)
1216      *day = wd->d_min;
1217 }
1218
1219 /**
1220  * Set if the datefield show hours in military or am/pm mode
1221  *
1222  * @param obj The datefield object
1223  * @param mode option for the hours mode. If true, it is shown as 12h mode, if false, it is shown as 24h mode. Default value is true 
1224  *
1225  * @ingroup Datefield
1226  */
1227 EAPI void
1228 elm_datefield_time_mode_set(Evas_Object *obj, Eina_Bool mode)
1229 {
1230    ELM_CHECK_WIDTYPE(obj, widtype);
1231    Widget_Data *wd = elm_widget_data_get(obj);
1232
1233    if (!wd) return;
1234
1235    if (wd->time_mode != mode) 
1236      {
1237         wd->time_mode = mode;
1238         if (!wd->time_mode) edje_object_signal_emit(wd->base, "elm,state,mode,24h", "elm");
1239         else edje_object_signal_emit(wd->base, "elm,state,mode,12h", "elm");
1240         _date_update(obj);
1241      }
1242 }
1243
1244 /**
1245  * get time mode of the datefield
1246  *
1247  * @param obj The datefield object
1248  * @return time mode (EINA_TRUE: 12hour mode / EINA_FALSE: 24hour mode) 
1249  *
1250  * @ingroup Datefield
1251  */
1252 EAPI Eina_Bool
1253 elm_datefield_time_mode_get(const Evas_Object *obj)
1254 {
1255    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1256    Widget_Data *wd = elm_widget_data_get(obj);
1257
1258    if (!wd) return EINA_FALSE;
1259
1260    return wd->time_mode;
1261 }
1262
1263 /**
1264  * Set date format of datefield
1265  *
1266  * @param obj The datefield object
1267  * @param fmt The date format, ex) yymmdd. Default value is mmddyy.
1268  *
1269  * @ingroup Datefield
1270  */
1271 EAPI void
1272 elm_datefield_date_format_set(Evas_Object *obj, const char *fmt)
1273 {
1274    ELM_CHECK_WIDTYPE(obj, widtype);
1275    Widget_Data *wd = elm_widget_data_get(obj);
1276    char sig[32] = "elm,state,format,";
1277    int i = 0, j;
1278
1279    if (!wd || !fmt) return;
1280
1281    j = strlen(sig);
1282    while (j < 32)
1283      {
1284         sig[j++] = tolower(fmt[i++]);
1285      }
1286    sig[j] = '\0';
1287    edje_object_signal_emit(wd->base, sig, "elm");
1288
1289    if (strstr(sig, "yymmdd")) wd->date_format = DATE_FORMAT_YYMMDD;
1290    else if (strstr(sig, "yyddmm")) wd->date_format = DATE_FORMAT_YYDDMM;
1291    else if (strstr(sig, "mmyydd")) wd->date_format = DATE_FORMAT_MMYYDD;
1292    else if (strstr(sig, "mmddyy")) wd->date_format = DATE_FORMAT_MMDDYY;
1293    else if (strstr(sig, "ddyymm")) wd->date_format = DATE_FORMAT_DDYYMM;
1294    else if (strstr(sig, "ddmmyy")) wd->date_format = DATE_FORMAT_DDMMYY;
1295    wd->format_exists = EINA_TRUE;
1296 }
1297
1298 /**
1299  * get date format of the datefield
1300  *
1301  * @param obj The datefield object
1302  * @return date format string. ex) yymmdd
1303  *
1304  * @ingroup Datefield
1305  */
1306 EAPI const char *
1307 elm_datefield_date_format_get(const Evas_Object *obj)
1308 {
1309    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1310    Widget_Data *wd = elm_widget_data_get(obj);
1311
1312    switch (wd->date_format)
1313      {
1314       case DATE_FORMAT_YYMMDD: return "yymmdd";
1315       case DATE_FORMAT_YYDDMM: return "yyddmm";
1316       case DATE_FORMAT_MMYYDD: return "mmyydd";
1317       case DATE_FORMAT_MMDDYY: return "mmddyy";
1318       case DATE_FORMAT_DDYYMM: return "ddyymm";
1319       case DATE_FORMAT_DDMMYY: return "ddmmyy";
1320      }
1321 }
1322
1323 /**
1324  * Add a callback function for input panel state
1325  *
1326  * @param obj The datefield object
1327  * @param func The function to be called when the event is triggered (value will be the Ecore_IMF_Input_Panel_State)
1328  * @param data The data pointer to be passed to @p func 
1329  *
1330  * @ingroup Datefield
1331  */
1332 EAPI void 
1333 elm_datefield_input_panel_state_callback_add(Evas_Object *obj, void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value), void *data)
1334 {
1335    ELM_CHECK_WIDTYPE(obj, widtype);
1336    Widget_Data *wd = elm_widget_data_get(obj);
1337    int i;
1338
1339    if (!wd) return;
1340
1341    if (wd->func && (wd->func != pEventCallbackFunc))
1342      elm_datefield_input_panel_state_callback_del(obj, wd->func);
1343
1344    if (wd->func != pEventCallbackFunc)
1345      {
1346         wd->func = pEventCallbackFunc;
1347         wd->func_data = data;
1348
1349         for (i = 0; i < DATE_MAX; i++)
1350           ecore_imf_context_input_panel_event_callback_add(
1351         elm_entry_imf_context_get(wd->date[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback, obj);
1352
1353         for (i = 0; i < TIME_MAX; i++)
1354           ecore_imf_context_input_panel_event_callback_add(
1355         elm_entry_imf_context_get(wd->time[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback, obj);
1356      }
1357 }
1358
1359 /**
1360  * Delete a callback function for input panel state
1361  *
1362  * @param obj The datefield object
1363  * @param func The function to be called when the event is triggered
1364  *
1365  * @ingroup Datefield
1366  */
1367 EAPI void 
1368 elm_datefield_input_panel_state_callback_del(Evas_Object *obj, void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value))
1369 {
1370    ELM_CHECK_WIDTYPE(obj, widtype);
1371    Widget_Data *wd = elm_widget_data_get(obj);
1372    int i;
1373
1374    if (!wd) return;
1375
1376    if (wd->func && wd->func == pEventCallbackFunc) 
1377      {
1378         for (i = 0; i < DATE_MAX; i++)
1379           ecore_imf_context_input_panel_event_callback_del(
1380         elm_entry_imf_context_get(wd->date[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback);
1381
1382         for (i = 0; i < TIME_MAX; i++)
1383           ecore_imf_context_input_panel_event_callback_del(
1384         elm_entry_imf_context_get(wd->time[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback);
1385
1386         wd->func = NULL;
1387         wd->func_data = NULL;
1388      }
1389 }