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