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