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